]> granicus.if.org Git - vim/commitdiff
updated for version 7.0067
authorBram Moolenaar <Bram@vim.org>
Sun, 17 Apr 2005 20:18:43 +0000 (20:18 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 17 Apr 2005 20:18:43 +0000 (20:18 +0000)
Makefile
src/spell.c

index afd8ad64c42f75b7e5144265aa6800c0b2db6580..7e916edb241b76fb02716221599610e8e36c8a8c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -282,6 +282,7 @@ unixrt: dist prepare
        tar cf - \
                $(RT_SCRIPTS) \
                $(LANG_GEN) \
+               $(LANG_GEN_BIN) \
                | (cd dist/$(VIMRTDIR); tar xf -)
        cd dist && tar cf $(VIMVER)-rt2.tar $(VIMRTDIR)
        gzip -9 dist/$(VIMVER)-rt2.tar
@@ -439,6 +440,7 @@ dosrt_unix2dos: dist prepare no_title.vim
                $(RT_UNIX_DOS_BIN) \
                $(RT_ALL_BIN) \
                $(RT_DOS_BIN) \
+               $(LANG_GEN_BIN) \
                | (cd dist/vim/$(VIMRTDIR); tar xf -)
        mv dist/vim/$(VIMRTDIR)/runtime/* dist/vim/$(VIMRTDIR)
        rmdir dist/vim/$(VIMRTDIR)/runtime
index e3a97fc83342d980187b8f991b5d382684839684..9f1f00c0071fdbde6f4536673b5d698258b37770 100644 (file)
@@ -903,6 +903,13 @@ spell_load_lang(lang)
        sprintf((char *)fname_enc, "spell/%s.%s.spl", lang, p);
 
        r = do_in_runtimepath(fname_enc, TRUE, spell_load_file, lp);
+       if (r == FAIL && !lp->sl_error)
+       {
+           /* Try loading the ASCII version. */
+           sprintf((char *)fname_enc, "spell/%s.ascii.spl", lang);
+
+           r = do_in_runtimepath(fname_enc, TRUE, spell_load_file, lp);
+       }
        if (r == FAIL || lp->sl_error)
        {
            slang_free(lp);
@@ -1001,8 +1008,8 @@ spell_load_file(fname, cookie)
     int                affitemcnt;
     int                bl_used = SBLOCKSIZE;
     int                widx;
-    int                prefm;      /* 1 if <= 256 prefixes, sizeof(short_u) otherw. */
-    int                suffm;      /* 1 if <= 256 suffixes, sizeof(short_u) otherw. */
+    int                prefm = 0;  /* 1 if <= 256 prefixes, sizeof(short_u) otherw. */
+    int                suffm = 0;  /* 1 if <= 256 suffixes, sizeof(short_u) otherw. */
     int                wlen;
     int                flags;
     affitem_T  *ai, *ai2, **aip;
@@ -1480,6 +1487,7 @@ did_set_spelllang(buf)
        e = vim_strchr(lang, ',');
        if (e == NULL)
            e = lang + STRLEN(lang);
+       region = NULL;
        if (e > lang + 2)
        {
            if (e - lang >= MAXWLEN)
@@ -1490,8 +1498,6 @@ did_set_spelllang(buf)
            if (lang[2] == '_')
                region = lang + 3;
        }
-       else
-           region = NULL;
 
        for (lp = first_lang; lp != NULL; lp = lp->sl_next)
            if (STRNICMP(lp->sl_name, lang, 2) == 0)
@@ -1726,7 +1732,13 @@ struct affentry_S
     affentry_T *ae_next;       /* next affix with same name/number */
     char_u     *ae_chop;       /* text to chop off basic word (can be NULL) */
     char_u     *ae_add;        /* text to add to basic word (can be NULL) */
-    char_u     *ae_add_nw;     /* first non-word character in "ae_add" */
+    char_u     *ae_add_nw;     /* For a suffix: first non-word char in
+                                * "ae_add"; for a prefix with only non-word
+                                * chars: equal to "ae_add", for a prefix with
+                                * word and non-word chars: first non-word
+                                * char after word char.  NULL otherwise. */
+    char_u     *ae_add_pw;     /* For a prefix with both word and non-word
+                                * chars: first word char.  NULL otherwise. */
     char_u     *ae_cond;       /* condition (NULL for ".") */
     regprog_T  *ae_prog;       /* regexp program for ae_cond or NULL */
     short_u    ae_affnr;       /* for old affix: new affix number */
@@ -1778,10 +1790,11 @@ static affhash_T dumas;
 #define HI2AS(hi)      ((affhash_T *)((hi)->hi_key - (dumas.as_word - (char_u *)&dumas)))
 
 
-static afffile_T *spell_read_aff __ARGS((char_u *fname, vimconv_T *conv));
+static afffile_T *spell_read_aff __ARGS((char_u *fname, vimconv_T *conv, int ascii));
 static void spell_free_aff __ARGS((afffile_T *aff));
-static int spell_read_dic __ARGS((hashtab_T *ht, char_u *fname, vimconv_T *conv));
-static int get_new_aff __ARGS((hashtab_T *oldaff, garray_T *gap));
+static int has_non_ascii __ARGS((char_u *s));
+static int spell_read_dic __ARGS((hashtab_T *ht, char_u *fname, vimconv_T *conv, int ascii));
+static int get_new_aff __ARGS((hashtab_T *oldaff, garray_T *gap, int prefix));
 static void spell_free_dic __ARGS((hashtab_T *dic));
 static int same_affentries __ARGS((affheader_T *ah1, affheader_T *ah2));
 static void add_affhash __ARGS((hashtab_T *ht, char_u *key, int newnr));
@@ -1801,15 +1814,17 @@ static void write_bword __ARGS((FILE *fd, basicword_T *bw, int lowcap, basicword
 static void free_wordtable __ARGS((hashtab_T *ht));
 static void free_basicword __ARGS((basicword_T *bw));
 static void free_affixentries __ARGS((affentry_T *first));
+static void free_affix_entry __ARGS((affentry_T *ap));
 
 /*
  * Read an affix ".aff" file.
  * Returns an afffile_T, NULL for failure.
  */
     static afffile_T *
-spell_read_aff(fname, conv)
+spell_read_aff(fname, conv, ascii)
     char_u     *fname;
     vimconv_T  *conv;          /* info for encoding conversion */
+    int                ascii;          /* Only accept ASCII characters */
 {
     FILE       *fd;
     afffile_T  *aff;
@@ -1895,7 +1910,7 @@ spell_read_aff(fname, conv)
                {
                    /* Setup for conversion from "ENC" to 'encoding'. */
                    aff->af_enc = enc_canonize(items[1]);
-                   if (aff->af_enc != NULL
+                   if (aff->af_enc != NULL && !ascii
                            && convert_setup(conv, aff->af_enc, p_enc) == FAIL)
                        smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
                                                   fname, aff->af_enc, p_enc);
@@ -1952,8 +1967,7 @@ spell_read_aff(fname, conv)
                                                (unsigned)sizeof(affentry_T));
                if (aff_entry == NULL)
                    break;
-               aff_entry->ae_next = cur_aff->ah_first;
-               cur_aff->ah_first = aff_entry;
+
                if (STRCMP(items[2], "0") != 0)
                    aff_entry->ae_chop = vim_strsave(items[2]);
                if (STRCMP(items[3], "0") != 0)
@@ -1969,6 +1983,19 @@ spell_read_aff(fname, conv)
                        sprintf((char *)buf, "%s$", items[4]);
                    aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING);
                }
+
+               if (ascii && (has_non_ascii(aff_entry->ae_chop)
+                                         || has_non_ascii(aff_entry->ae_add)))
+               {
+                   /* Don't use an affix entry with non-ASCII characters when
+                    * "ascii" is TRUE. */
+                   free_affix_entry(aff_entry);
+               }
+               else
+               {
+                   aff_entry->ae_next = cur_aff->ah_first;
+                   cur_aff->ah_first = aff_entry;
+               }
            }
            else if (STRCMP(items[0], "REP") == 0 && itemcnt == 2)
                /* Ignore REP count */;
@@ -1996,6 +2023,23 @@ spell_read_aff(fname, conv)
     return aff;
 }
 
+/*
+ * Return TRUE if string "s" contains a non-ASCII character (128 or higher).
+ * When "s" is NULL FALSE is returned.
+ */
+    static int
+has_non_ascii(s)
+    char_u     *s;
+{
+    char_u     *p;
+
+    if (s != NULL)
+       for (p = s; *p != NUL; ++p)
+           if (*p >= 128)
+               return TRUE;
+    return FALSE;
+}
+
 /*
  * Free the structure filled by spell_read_aff().
  */
@@ -2049,10 +2093,11 @@ spell_free_aff(aff)
  * Each entry in the hashtab_T is a dicword_T.
  */
     static int
-spell_read_dic(ht, fname, conv)
+spell_read_dic(ht, fname, conv, ascii)
     hashtab_T  *ht;
     char_u     *fname;
     vimconv_T  *conv;          /* info for encoding conversion */
+    int                ascii;          /* only accept ASCII words */
 {
     char_u     line[MAXLINELEN];
     char_u     *p;
@@ -2102,6 +2147,10 @@ spell_read_dic(ht, fname, conv)
        if (p != NULL)
            *p++ = NUL;
 
+       /* Skip non-ASCII words when "ascii" is TRUE. */
+       if (ascii && has_non_ascii(line))
+           continue;
+
        /* Convert from "SET" to 'encoding' when needed. */
        if (conv->vc_type != CONV_NONE)
        {
@@ -2170,9 +2219,11 @@ spell_free_dic(dic)
  * Returns OK or FAIL;
  */
     static int
-get_new_aff(oldaff, gap)
+get_new_aff(oldaff, gap, prefix)
     hashtab_T  *oldaff;        /* hashtable with affheader_T */
     garray_T   *gap;           /* table with new affixes */
+    int                prefix;         /* TRUE when doing prefixes, FALSE for
+                                  suffixes */
 {
     int                oldtodo;
     affheader_T        *oldah, *newah, *gapah;
@@ -2218,17 +2269,44 @@ get_new_aff(oldaff, gap)
                                                       oldae = oldae->ae_next)
            {
                oldae->ae_add_nw = NULL;
+               oldae->ae_add_pw = NULL;
                if (oldae->ae_add != NULL)
                {
-                   /* Check for non-word characters in the suffix.  If there
+                   /* Check for non-word characters in the affix.  If there
                     * is one this affix will be turned into an addition.
                     * This is stored with the old affix, that is where
                     * trans_affixes() will check. */
                    for (p = oldae->ae_add; *p != NUL; mb_ptr_adv(p))
                        if (!spell_iswordc(p))
+                       {
+                           oldae->ae_add_nw = p;
                            break;
-                   if (*p != NUL)
-                       oldae->ae_add_nw = p;
+                       }
+
+                   if (prefix && oldae->ae_add_nw != NULL)
+                   {
+                       /* If a prefix has both word and non-word characters
+                        * special treatment is necessary.  If it has only
+                        * non-word characters it becomes a leadstring. */
+                       for (p = oldae->ae_add; *p != NUL; mb_ptr_adv(p))
+                           if (spell_iswordc(p))
+                           {
+                               oldae->ae_add_pw = p;
+                               break;
+                           }
+                       if (oldae->ae_add_pw != NULL)
+                       {
+                           /* Mixed prefix, set ae_add_nw to first non-word
+                            * char after ae_add_pw (if there is one). */
+                           oldae->ae_add_nw = NULL;
+                           for ( ; *p != NUL; mb_ptr_adv(p))
+                               if (!spell_iswordc(p))
+                               {
+                                   oldae->ae_add_nw = p;
+                                   break;
+                               }
+                       }
+                   }
                }
 
                if (oldae->ae_cond == NULL)
@@ -2458,12 +2536,14 @@ trans_affixes(dw, bw, oldaff, newwords)
     basicword_T *nbw;
     int                alen;
     int                wlen;
-    garray_T   fixga;
+    garray_T   suffixga;       /* list of words with non-word suffixes */
+    garray_T   prefixga;       /* list of words with non-word prefixes */
     char_u     nword[MAXWLEN];
     int                flags;
     int                n;
 
-    ga_init2(&fixga, (int)sizeof(basicword_T *), 5);
+    ga_init2(&suffixga, (int)sizeof(basicword_T *), 5);
+    ga_init2(&prefixga, (int)sizeof(basicword_T *), 5);
 
     /* Loop over all the affix names of the old word. */
     key[1] = NUL;
@@ -2494,8 +2574,8 @@ trans_affixes(dw, bw, oldaff, newwords)
            if (ae->ae_prog == NULL
                           || vim_regexec(&regmatch, dw->dw_word, (colnr_T)0))
            {
-               if (ae->ae_add_nw != NULL && (gap == &bw->bw_suffix
-                           ? bw->bw_addstring : bw->bw_leadstring) == NULL)
+               if ((ae->ae_add_nw != NULL || ae->ae_add_pw != NULL)
+                       && (gap != &bw->bw_suffix || bw->bw_addstring == NULL))
                {
                    /* Affix has a non-word character and isn't prepended to
                     * leader or appended to addition.  Need to use another
@@ -2527,6 +2607,7 @@ trans_affixes(dw, bw, oldaff, newwords)
                            flags = captype(nword, nword + STRLEN(nword));
                            if (flags & BWF_KEEPCAP)
                            {
+                               /* "caseword" excludes the addition */
                                nword[STRLEN(dw->dw_word) + alen] = NUL;
                                nbw->bw_caseword = vim_strsave(nword);
                            }
@@ -2542,8 +2623,9 @@ trans_affixes(dw, bw, oldaff, newwords)
                            STRCPY(nbw->bw_word, bw->bw_word);
                            if (alen > 0 || ae->ae_chop != NULL)
                            {
-                               /* Suffix starts with word character.  Append
-                                * it to the word.  Add new word entry. */
+                               /* Suffix starts with word character and/or
+                                * chop off something.  Append it to the word.
+                                * Add new word entry. */
                                wlen = STRLEN(nbw->bw_word);
                                if (ae->ae_chop != NULL)
                                    wlen -= STRLEN(ae->ae_chop);
@@ -2558,15 +2640,154 @@ trans_affixes(dw, bw, oldaff, newwords)
                                bw->bw_next = nbw;
 
                            /* Remember this word, we need to set bw_prefix
+                            * and bw_prefix later. */
+                           if (ga_grow(&suffixga, 1) == OK)
+                               ((basicword_T **)suffixga.ga_data)
+                                                   [suffixga.ga_len++] = nbw;
+                       }
+                   }
+                   else if (ae->ae_add_nw == NULL)
+                   {
+                       /* Prefix that starts with non-word char(s) and may be
+                        * followed by word chars: Make a leadstring and
+                        * prepend word chars before the word. */
+                       alen = STRLEN(ae->ae_add_pw);
+                       nbw = (basicword_T *)alloc((unsigned)(
+                                   sizeof(basicword_T) + STRLEN(bw->bw_word)
+                                                                + alen + 1));
+                       if (nbw != NULL)
+                       {
+                           *nbw = *bw;
+                           ga_init2(&nbw->bw_prefix, sizeof(short_u), 1);
+                           ga_init2(&nbw->bw_suffix, sizeof(short_u), 1);
+
+                           /* Adding the prefix may change the caps. */
+                           STRCPY(nword, ae->ae_add);
+                           p = dw->dw_word;
+                           if (ae->ae_chop != NULL)
+                               /* Skip chop string. */
+                               for (i = mb_charlen(ae->ae_chop); i > 0; --i)
+                                   mb_ptr_adv( p);
+                           STRCAT(nword, p);
+
+                           flags = captype(nword, nword + STRLEN(nword));
+                           if (flags & BWF_KEEPCAP)
+                               /* "caseword" excludes the addition */
+                               nbw->bw_caseword = vim_strsave(nword
+                                             + (ae->ae_add_pw - ae->ae_add));
+                           else
+                               nbw->bw_caseword = NULL;
+                           nbw->bw_flags &= ~(BWF_ONECAP | BWF_ALLCAP
+                                                              | BWF_KEEPCAP);
+                           nbw->bw_flags |= flags;
+
+                           if (bw->bw_addstring != NULL)
+                               nbw->bw_addstring =
+                                              vim_strsave(bw->bw_addstring);
+                           else
+                               nbw->bw_addstring = NULL;
+                           nbw->bw_leadstring = vim_strnsave(ae->ae_add,
+                                                 ae->ae_add_pw - ae->ae_add);
+
+                           if (alen > 0 || ae->ae_chop != NULL)
+                           {
+                               /* Prefix ends in word character and/or chop
+                                * off something.  Prepend it to the word.
+                                * Add new word entry. */
+                               STRCPY(nbw->bw_word, ae->ae_add_pw);
+                               p = bw->bw_word;
+                               if (ae->ae_chop != NULL)
+                                   p += STRLEN(ae->ae_chop);
+                               STRCAT(nbw->bw_word, p);
+                               add_to_wordlist(newwords, nbw);
+                           }
+                           else
+                           {
+                               /* Basic word is the same, link "nbw" after
+                                * "bw". */
+                               STRCPY(nbw->bw_word, bw->bw_word);
+                               bw->bw_next = nbw;
+                           }
+
+                           /* Remember this word, we need to set bw_suffix
                             * and bw_suffix later. */
-                           if (ga_grow(&fixga, 1) == OK)
-                               ((basicword_T **)fixga.ga_data)[fixga.ga_len++]
-                                                                       = nbw;
+                           if (ga_grow(&prefixga, 1) == OK)
+                               ((basicword_T **)prefixga.ga_data)
+                                                   [prefixga.ga_len++] = nbw;
                        }
                    }
                    else
                    {
-                       /* TODO: prefix with non-word char */
+                       /* Prefix with both non-word and word characters: Turn
+                        * prefix into basic word, original word becomes an
+                        * addstring. */
+
+                       /* Fold-case the word characters in the prefix into
+                        * nword[]. */
+                       alen = 0;
+                       for (p = ae->ae_add_pw; p < ae->ae_add_nw; p += n)
+                       {
+#ifdef FEAT_MBYTE
+                           n = (*mb_ptr2len_check)(p);
+#else
+                           n = 1;
+#endif
+                           (void)str_foldcase(p, n, nword + alen,
+                                                             MAXWLEN - alen);
+                           alen += STRLEN(nword + alen);
+                       }
+
+                       /* Allocate a new word entry. */
+                       nbw = (basicword_T *)alloc((unsigned)(
+                                            sizeof(basicword_T) + alen + 1));
+                       if (nbw != NULL)
+                       {
+                           *nbw = *bw;
+                           ga_init2(&nbw->bw_prefix, sizeof(short_u), 1);
+                           ga_init2(&nbw->bw_suffix, sizeof(short_u), 1);
+
+                           mch_memmove(nbw->bw_word, nword, alen);
+                           nbw->bw_word[alen] = NUL;
+
+                           /* Use the cap type of the prefix. */
+                           alen = ae->ae_add_nw - ae->ae_add_pw;
+                           mch_memmove(nword, ae->ae_add_pw, alen);
+                           nword[alen] = NUL;
+                           flags = captype(nword, nword + STRLEN(nword));
+                           if (flags & BWF_KEEPCAP)
+                               nbw->bw_caseword = vim_strsave(nword);
+                           else
+                               nbw->bw_caseword = NULL;
+                           nbw->bw_flags &= ~(BWF_ONECAP | BWF_ALLCAP
+                                                              | BWF_KEEPCAP);
+                           nbw->bw_flags |= flags;
+
+                           /* The addstring is the prefix after the word
+                            * characters, the original word excluding "chop",
+                            * plus any addition. */
+                           STRCPY(nword, ae->ae_add_nw);
+                           p = bw->bw_word;
+                           if (ae->ae_chop != NULL)
+                               p += STRLEN(ae->ae_chop);
+                           STRCAT(nword, p);
+                           if (bw->bw_addstring != NULL)
+                               STRCAT(nword, bw->bw_addstring);
+                           nbw->bw_addstring = vim_strsave(nword);
+
+                           if (ae->ae_add_pw > ae->ae_add)
+                               nbw->bw_leadstring = vim_strnsave(ae->ae_add,
+                                                 ae->ae_add_pw - ae->ae_add);
+                           else
+                               nbw->bw_leadstring = NULL;
+
+                           add_to_wordlist(newwords, nbw);
+
+                           /* Remember this word, we need to set bw_suffix
+                            * and bw_suffix later. */
+                           if (ga_grow(&prefixga, 1) == OK)
+                               ((basicword_T **)prefixga.ga_data)
+                                                   [prefixga.ga_len++] = nbw;
+                       }
                    }
                }
                else
@@ -2601,11 +2822,10 @@ trans_affixes(dw, bw, oldaff, newwords)
     /*
      * For the words that we added for suffixes with non-word characters: Use
      * the prefix list of the main word.
-     * TODO: do the same for prefixes.
      */
-    for (i = 0; i < fixga.ga_len; ++i)
+    for (i = 0; i < suffixga.ga_len; ++i)
     {
-       nbw = ((basicword_T **)fixga.ga_data)[i];
+       nbw = ((basicword_T **)suffixga.ga_data)[i];
        if (ga_grow(&nbw->bw_prefix, bw->bw_prefix.ga_len) == OK)
        {
            mch_memmove(nbw->bw_prefix.ga_data, bw->bw_prefix.ga_data,
@@ -2614,7 +2834,23 @@ trans_affixes(dw, bw, oldaff, newwords)
        }
     }
 
-    ga_clear(&fixga);
+    /*
+     * For the words that we added for prefixes with non-word characters: Use
+     * the suffix list of the main word.
+     */
+    for (i = 0; i < prefixga.ga_len; ++i)
+    {
+       nbw = ((basicword_T **)prefixga.ga_data)[i];
+       if (ga_grow(&nbw->bw_suffix, bw->bw_suffix.ga_len) == OK)
+       {
+           mch_memmove(nbw->bw_suffix.ga_data, bw->bw_suffix.ga_data,
+                                     bw->bw_suffix.ga_len * sizeof(short_u));
+           nbw->bw_suffix.ga_len = bw->bw_suffix.ga_len;
+       }
+    }
+
+    ga_clear(&suffixga);
+    ga_clear(&prefixga);
 }
 
 /*
@@ -2642,8 +2878,9 @@ build_wordlist(newwords, oldwords, oldaff, regionmask)
     char_u     *p;
     int                clen;
     int                flags;
-    char_u     *cp;
+    char_u     *cp = NULL;
     int                l;
+    char_u     message[MAXLINELEN + MAXWLEN];
 
     todo = oldwords->ht_used;
     for (old_hi = oldwords->ht_array; todo > 0; ++old_hi)
@@ -2654,14 +2891,15 @@ build_wordlist(newwords, oldwords, oldaff, regionmask)
            dw = HI2DW(old_hi);
 
            /* This takes time, print a message now and then. */
-           if ((todo & 0x3ff) == 0 || todo == oldwords->ht_used - 1)
+           if ((todo & 0x3ff) == 0 || todo == (int)oldwords->ht_used - 1)
            {
-               if (todo != oldwords->ht_used - 1)
-               {
-                   msg_didout = FALSE;
-                   msg_col = 0;
-               }
-               smsg((char_u *)_("%6d todo - %s"), todo, dw->dw_word);
+               sprintf((char *)message, _("%6d todo - %s"),
+                                                          todo, dw->dw_word);
+               msg_start();
+               msg_outtrans_attr(message, 0);
+               msg_clr_eos();
+               msg_didout = FALSE;
+               msg_col = 0;
                out_flush();
                ui_breakcheck();
                if (got_int)
@@ -2874,6 +3112,7 @@ expand_affixes(newwords, prefgap, suffgap)
     affentry_T *pae, *sae;
     garray_T   add_words;
     int                n;
+    char_u     message[MAXLINELEN + MAXWLEN];
 
     ga_init2(&add_words, sizeof(basicword_T *), 10);
 
@@ -2883,6 +3122,23 @@ expand_affixes(newwords, prefgap, suffgap)
        if (!HASHITEM_EMPTY(hi))
        {
            --todo;
+
+           /* This takes time, print a message now and then. */
+           if ((todo & 0x3ff) == 0 || todo == (int)newwords->ht_used - 1)
+           {
+               sprintf((char *)message, _("%6d todo - %s"),
+                                                   todo, HI2BW(hi)->bw_word);
+               msg_start();
+               msg_outtrans_attr(message, 0);
+               msg_clr_eos();
+               msg_didout = FALSE;
+               msg_col = 0;
+               out_flush();
+               ui_breakcheck();
+               if (got_int)
+                   break;
+           }
+
            for (bw = HI2BW(hi); bw != NULL; bw = bw->bw_next)
            {
                /*
@@ -3318,7 +3574,7 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
     char_u     **wtab;
     int                todo;
     int                flags, aflags;
-    basicword_T        *bw, *bwf, *bw2, *prevbw = NULL;
+    basicword_T        *bw, *bwf, *bw2 = NULL, *prevbw = NULL;
     int                regionmask;     /* mask for all relevant region bits */
     int                i;
     int                cnt;
@@ -3397,7 +3653,7 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
 
        /* Now write each basic word to the spell file. */
        ga_init2(&bwga, sizeof(basicword_T *), 10);
-       for (todo = 0; todo < newwords->ht_used; ++todo)
+       for (todo = 0; (long_u)todo < newwords->ht_used; ++todo)
        {
            bwf = KEY2BW(wtab[todo]);
 
@@ -3661,9 +3917,17 @@ ex_mkspell(eap)
     struct stat        st;
     int                round;
     vimconv_T  conv;
+    int                ascii = FALSE;
+    char_u     *arg = eap->arg;
+
+    if (STRNCMP(arg, "-ascii", 6) == 0)
+    {
+       ascii = TRUE;
+       arg = skipwhite(arg + 6);
+    }
 
-    /* Expand all the arguments (e.g., $VIMRUNTIME). */
-    if (get_arglist_exp(eap->arg, &fcount, &fnames) == FAIL)
+    /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */
+    if (get_arglist_exp(arg, &fcount, &fnames) == FAIL)
        return;
     if (fcount < 2)
        EMSG(_(e_invarg));      /* need at least output and input names */
@@ -3673,7 +3937,8 @@ ex_mkspell(eap)
     {
        /* Check for overwriting before doing things that may take a lot of
         * time. */
-       sprintf((char *)wfname, "%s.%s.spl", fnames[0], p_enc);
+       sprintf((char *)wfname, "%s.%s.spl", fnames[0],
+                                          ascii ? (char_u *)"ascii" : p_enc);
        if (!eap->forceit && mch_stat((char *)wfname, &st) >= 0)
        {
            EMSG(_(e_exists));
@@ -3719,12 +3984,12 @@ ex_mkspell(eap)
            /* Read the .aff file.  Will init "conv" based on the "SET" line. */
            conv.vc_type = CONV_NONE;
            sprintf((char *)fname, "%s.aff", fnames[i]);
-           if ((afile[i - 1] = spell_read_aff(fname, &conv)) == NULL)
+           if ((afile[i - 1] = spell_read_aff(fname, &conv, ascii)) == NULL)
                break;
 
            /* Read the .dic file. */
            sprintf((char *)fname, "%s.dic", fnames[i]);
-           if (spell_read_dic(&dfile[i - 1], fname, &conv) == FAIL)
+           if (spell_read_dic(&dfile[i - 1], fname, &conv, ascii) == FAIL)
                break;
 
            /* Free any conversion stuff. */
@@ -3755,7 +4020,8 @@ ex_mkspell(eap)
                ga_init2(gap, sizeof(affheader_T), 50);
                for (i = 1; i < fcount; ++i)
                    get_new_aff(round == 1 ? &afile[i - 1]->af_pref
-                                          : &afile[i - 1]->af_suff, gap);
+                                          : &afile[i - 1]->af_suff,
+                                          gap, round == 1);
            }
 
            /*
@@ -3863,7 +4129,7 @@ free_basicword(bw)
 }
 
 /*
- * Free a list of affentry_T.
+ * Free a list of affentry_T and what they contain.
  */
     static void
 free_affixentries(first)
@@ -3874,909 +4140,24 @@ free_affixentries(first)
     for (ap = first; ap != NULL; ap = an)
     {
        an = ap->ae_next;
-       vim_free(ap->ae_chop);
-       vim_free(ap->ae_add);
-       vim_free(ap->ae_cond);
-       vim_free(ap->ae_prog);
-       vim_free(ap);
+       free_affix_entry(ap);
     }
 }
 
-#endif  /* FEAT_MBYTE */
-
-#endif  /* FEAT_SYN_HL */
-
-#if 0  /* old spell code with words in .spl file */
-/*
- * Structure that is used to store the text from the language file.  This
- * avoids the need to allocate space for each individual word.  It's allocated
- * in big chunks for speed.
- */
-#define  SBLOCKSIZE 4096       /* default size of sb_data */
-typedef struct sblock_S sblock_T;
-struct sblock_S
-{
-    sblock_T   *sb_next;       /* next block in list */
-    char_u     sb_data[1];     /* data, actually longer */
-};
-
-/* Structure to store words and additions.  Used twice : once for case-folded
- * and once for keep-case words. */
-typedef struct winfo_S
-{
-    hashtab_T  wi_ht;          /* hashtable with all words, both dword_T and
-                                  nword_T (check flags for DW_NWORD) */
-    garray_T   wi_add;         /* table with pointers to additions in a
-                                  dword_T */
-    int                wi_addlen;      /* longest addition length */
-} winfo_T;
-
-/*
- * Structure used to store words and other info for one language.
- */
-typedef struct slang_S slang_T;
-struct slang_S
-{
-    slang_T    *sl_next;       /* next language */
-    char_u     sl_name[2];     /* language name "en", "nl", etc. */
-    winfo_T    sl_fwords;      /* case-folded words and additions */
-    winfo_T    sl_kwords;      /* keep-case words and additions */
-    char_u     sl_regions[17]; /* table with up to 8 region names plus NUL */
-    sblock_T   *sl_block;      /* list with allocated memory blocks */
-};
-
-static slang_T *first_lang = NULL;
-
-/* Entry for dword in "sl_ht".  Also used for part of an nword, starting with
- * the first non-word character.  And used for additions in wi_add. */
-typedef struct dword_S
-{
-    char_u     dw_region;      /* one bit per region where it's valid */
-    char_u     dw_flags;       /* DW_ flags */
-    char_u     dw_word[1];     /* actually longer, NUL terminated */
-} dword_T;
-
-#define REGION_ALL 0xff
-
-#define HI2DWORD(hi) (dword_T *)(hi->hi_key - 2)
-
-/* Entry for a nword in "sl_ht".  Note that the last three items must be
- * identical to dword_T, so that they can be in the same hashtable. */
-typedef struct nword_S
-{
-    garray_T   nw_ga;          /* table with pointers to dword_T for part
-                                  starting with non-word character */
-    int                nw_maxlen;      /* longest nword length (after the dword) */
-    char_u     nw_region;      /* one bit per region where it's valid */
-    char_u     nw_flags;       /* DW_ flags */
-    char_u     nw_word[1];     /* actually longer, NUL terminated */
-} nword_T;
-
-/* Get nword_T pointer from hashitem that uses nw_word */
-static nword_T dumnw;
-#define HI2NWORD(hi)   ((nword_T *)((hi)->hi_key - (dumnw.nw_word - (char_u *)&dumnw)))
-
-#define DW_CAP     0x01        /* word must start with capital */
-#define DW_RARE            0x02        /* rare word */
-#define DW_NWORD    0x04       /* this is an nword_T */
-#define DW_DWORD    0x08       /* (also) use as dword without nword */
-
-/*
- * Structure used in "b_langp", filled from 'spelllang'.
- */
-typedef struct langp_S
-{
-    slang_T    *lp_slang;      /* info for this language (NULL for last one) */
-    int                lp_region;      /* bitmask for region or REGION_ALL */
-} langp_T;
-
-#define LANGP_ENTRY(ga, i)     (((langp_T *)(ga).ga_data) + (i))
-#define DWORD_ENTRY(gap, i)    *(((dword_T **)(gap)->ga_data) + i)
-
-#define SP_OK          0
-#define SP_BAD         1
-#define SP_RARE                2
-#define SP_LOCAL       3
-
-static char *e_invchar2 = N_("E753: Invalid character in \"%s\"");
-
-static slang_T *spell_load_lang __ARGS((char_u *lang));
-static void spell_load_file __ARGS((char_u *fname));
-static int find_region __ARGS((char_u *rp, char_u *region));
-
 /*
- * Main spell-checking function.
- * "ptr" points to 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.
- * This must only be called when 'spelllang' is not empty.
- * Returns the length of the word in bytes, also when it's OK, so that the
- * caller can skip over the word.
+ * Free one affentry_T and what it contains.
  */
-    int
-spell_check(wp, ptr, attrp)
-    win_T      *wp;            /* current window */
-    char_u     *ptr;
-    int                *attrp;
+    static void
+free_affix_entry(ap)
+    affentry_T *ap;
 {
-    char_u     *e;             /* end of word */
-    char_u     *ne;            /* new end of word */
-    char_u     *me;            /* max. end of match */
-    langp_T    *lp;
-    int                result;
-    int                len = 0;
-    hashitem_T *hi;
-    int                round;
-    char_u     kword[MAXWLEN + 1];     /* word copy */
-    char_u     fword[MAXWLEN + 1];     /* word with case folded */
-    char_u     match[MAXWLEN + 1];     /* fword with additional chars */
-    char_u     kwordclen[MAXWLEN + 1]; /* len of orig chars after kword[] */
-    char_u     fwordclen[MAXWLEN + 1]; /* len of chars after fword[] */
-    char_u     *clen;
-    int                cidx = 0;               /* char index in xwordclen[] */
-    hash_T     fhash;                  /* hash for fword */
-    hash_T     khash;                  /* hash for kword */
-    int                match_len = 0;          /* length of match[] */
-    int                fmatch_len = 0;         /* length of nword match in chars */
-    garray_T   *gap;
-    int                l, t;
-    char_u     *p, *tp;
-    int                n;
-    dword_T    *dw;
-    dword_T    *tdw;
-    winfo_T    *wi;
-    nword_T    *nw;
-    int                w_isupper;
-
-    /* Find the end of the word.  We already know that *ptr is a word char. */
-    e = ptr;
-    do
-    {
-       mb_ptr_adv(e);
-       ++len;
-    } while (*e != NUL && spell_iswordc(e));
-
-    /* A word starting with a number is always OK. */
-    if (*ptr >= '0' && *ptr <= '9')
-       return (int)(e - ptr);
-
-#ifdef FEAT_MBYTE
-    w_isupper = MB_ISUPPER(mb_ptr2char(ptr));
-#else
-    w_isupper = MB_ISUPPER(*ptr);
-#endif
-
-    /* Make a copy of the word so that it can be NUL terminated.
-     * Compute hash value. */
-    mch_memmove(kword, ptr, e - ptr);
-    kword[e - ptr] = NUL;
-    khash = hash_hash(kword);
-
-    /* Make case-folded copy of the Word.  Compute its hash value. */
-    (void)str_foldcase(ptr, e - ptr, fword, MAXWLEN + 1);
-    fhash = hash_hash(fword);
-
-    /* Further case-folded characters to check for an nword match go in
-     * match[]. */
-    me = e;
-
-    /* "ne" is the end for the longest match */
-    ne = e;
-
-    /* The word is bad unless we find it in the dictionary. */
-    result = SP_BAD;
-
-    /*
-     * Loop over the languages specified in 'spelllang'.
-     * We check them all, because a matching nword may be longer than an
-     * already found dword or nword.
-     */
-    for (lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0); lp->lp_slang != NULL; ++lp)
-    {
-       /*
-        * Check for a matching word in the hashtable.
-        * Check both the keep-case word and the fold-case word.
-        */
-       for (round = 0; round <= 1; ++round)
-       {
-           if (round == 0)
-           {
-               wi = &lp->lp_slang->sl_kwords;
-               hi = hash_lookup(&wi->wi_ht, kword, khash);
-           }
-           else
-           {
-               wi = &lp->lp_slang->sl_fwords;
-               hi = hash_lookup(&wi->wi_ht, fword, fhash);
-           }
-           if (!HASHITEM_EMPTY(hi))
-           {
-               /*
-                * If this is an nword entry, check for match with remainder.
-                */
-               dw = HI2DWORD(hi);
-               if (dw->dw_flags & DW_NWORD)
-               {
-                   /* If the word is not defined as a dword we must find an
-                    * nword. */
-                   if ((dw->dw_flags & DW_DWORD) == 0)
-                       dw = NULL;
-
-                   /* Fold more characters when needed for the nword.  Need
-                    * to do one extra to check for a non-word character after
-                    * the nword.  Also keep the byte-size of each character,
-                    * both before and after folding case. */
-                   nw = HI2NWORD(hi);
-                   while ((round == 0
-                               ? me - e <= nw->nw_maxlen
-                               : match_len <= nw->nw_maxlen)
-                           && *me != NUL)
-                   {
-#ifdef FEAT_MBYTE
-                       l = mb_ptr2len_check(me);
-#else
-                       l = 1;
-#endif
-                       (void)str_foldcase(me, l, match + match_len,
-                                                    MAXWLEN - match_len + 1);
-                       me += l;
-                       kwordclen[cidx] = l;
-                       fwordclen[cidx] = STRLEN(match + match_len);
-                       match_len += fwordclen[cidx];
-                       ++cidx;
-                   }
-
-                   if (round == 0)
-                   {
-                       clen = kwordclen;
-                       tp = e;
-                   }
-                   else
-                   {
-                       clen = fwordclen;
-                       tp = match;
-                   }
-
-                   /* Match with each item.  The longest match wins:
-                    * "you've" is longer than "you". */
-                   gap = &nw->nw_ga;
-                   for (t = 0; t < gap->ga_len; ++t)
-                   {
-                       /* Skip entries with wrong case for first char.
-                        * Continue if it's a rare word without a captial. */
-                       tdw = DWORD_ENTRY(gap, t);
-                       if ((tdw->dw_flags & (DW_CAP | DW_RARE)) == DW_CAP
-                                                               && !w_isupper)
-                           continue;
-
-                       p = tdw->dw_word;
-                       l = 0;
-                       for (n = 0; p[n] != 0; n += clen[l++])
-                           if (vim_memcmp(p + n, tp + n, clen[l]) != 0)
-                               break;
+    vim_free(ap->ae_chop);
+    vim_free(ap->ae_add);
+    vim_free(ap->ae_cond);
+    vim_free(ap->ae_prog);
+    vim_free(ap);
+}
 
-                       /* Use a match if it's longer than previous matches
-                        * and the next character is not a word character. */
-                       if (p[n] == 0 && l > fmatch_len && (tp[n] == 0
-                                                  || !spell_iswordc(tp + n)))
-                       {
-                           dw = tdw;
-                           fmatch_len = l;
-                           if (round == 0)
-                               ne = tp + n;
-                           else
-                           {
-                               /* Need to use the length of the original
-                                * chars, not the fold-case ones. */
-                               ne = e;
-                               for (l = 0; l < fmatch_len; ++l)
-                                   ne += kwordclen[l];
-                           }
-                           if ((lp->lp_region & tdw->dw_region) == 0)
-                               result = SP_LOCAL;
-                           else if ((tdw->dw_flags & DW_CAP) && !w_isupper)
-                               result = SP_RARE;
-                           else
-                               result = SP_OK;
-                       }
-                   }
+#endif  /* FEAT_MBYTE */
 
-               }
-
-               if (dw != NULL)
-               {
-                   if (dw->dw_flags & DW_CAP)
-                   {
-                       /* Need to check first letter is uppercase.  If it is,
-                        * check region.  If it isn't it may be a rare word.
-                        * */
-                       if (w_isupper)
-                       {
-                           if ((dw->dw_region & lp->lp_region) == 0)
-                               result = SP_LOCAL;
-                           else
-                               result = SP_OK;
-                       }
-                       else if (dw->dw_flags & DW_RARE)
-                           result = SP_RARE;
-                   }
-                   else
-                   {
-                       if ((dw->dw_region & lp->lp_region) == 0)
-                           result = SP_LOCAL;
-                       else if (dw->dw_flags & DW_RARE)
-                           result = SP_RARE;
-                       else
-                           result = SP_OK;
-                   }
-               }
-           }
-       }
-
-       /*
-        * Check for an addition.
-        * Only after a dword, not after an nword.
-        * Check both the keep-case word and the fold-case word.
-        */
-       if (fmatch_len == 0)
-           for (round = 0; round <= 1; ++round)
-           {
-               if (round == 0)
-                   wi = &lp->lp_slang->sl_kwords;
-               else
-                   wi = &lp->lp_slang->sl_fwords;
-               gap = &wi->wi_add;
-               if (gap->ga_len == 0)   /* no additions, skip quickly */
-                   continue;
-
-               /* Fold characters when needed for the addition.  Need to do one
-                * extra to check for a word character after the addition. */
-               while ((round == 0
-                           ? me - e <= wi->wi_addlen
-                           : match_len <= wi->wi_addlen)
-                       && *me != NUL)
-               {
-#ifdef FEAT_MBYTE
-                   l = mb_ptr2len_check(me);
-#else
-                   l = 1;
-#endif
-                   (void)str_foldcase(me, l, match + match_len,
-                                                        MAXWLEN - match_len + 1);
-                   me += l;
-                   kwordclen[cidx] = l;
-                   fwordclen[cidx] = STRLEN(match + match_len);
-                   match_len += fwordclen[cidx];
-                   ++cidx;
-               }
-
-               if (round == 0)
-               {
-                   clen = kwordclen;
-                   tp = e;
-               }
-               else
-               {
-                   clen = fwordclen;
-                   tp = match;
-               }
-
-               /* Addition lookup.  Uses a linear search, there should be
-                * very few.  If there is a match adjust "ne" to the end.
-                * This doesn't change whether a word was good or bad, only
-                * the length. */
-               for (t = 0; t < gap->ga_len; ++t)
-               {
-                   tdw = DWORD_ENTRY(gap, t);
-                   p = tdw->dw_word;
-                   l = 0;
-                   for (n = 0; p[n] != 0; n += clen[l++])
-                       if (vim_memcmp(p + n, tp + n, clen[l]) != 0)
-                           break;
-
-                   /* Use a match if it's longer than previous matches
-                    * and the next character is not a word character. */
-                   if (p[n] == 0 && l > fmatch_len
-                                   && (tp[n] == 0 || !spell_iswordc(tp + n)))
-                   {
-                       fmatch_len = l;
-                       if (round == 0)
-                           ne = tp + n;
-                       else
-                       {
-                           /* Need to use the length of the original
-                            * chars, not the fold-case ones. */
-                           ne = e;
-                           for (l = 0; l < fmatch_len; ++l)
-                               ne += kwordclen[l];
-                       }
-                   }
-               }
-           }
-    }
-
-    if (result != SP_OK)
-    {
-       if (result == SP_BAD)
-           *attrp = highlight_attr[HLF_SPB];
-       else if (result == SP_RARE)
-           *attrp = highlight_attr[HLF_SPR];
-       else
-           *attrp = highlight_attr[HLF_SPL];
-    }
-
-    return (int)(ne - ptr);
-}
-
-static slang_T     *load_lp;   /* passed from spell_load_lang() to
-                                  spell_load_file() */
-
-/*
- * Load language "lang[2]".
- */
-    static slang_T *
-spell_load_lang(lang)
-    char_u     *lang;
-{
-    slang_T    *lp;
-    char_u     fname_enc[80];
-    char_u     fname_ascii[20];
-    char_u     *p;
-    int                r;
-
-    lp = (slang_T *)alloc(sizeof(slang_T));
-    if (lp != NULL)
-    {
-       lp->sl_name[0] = lang[0];
-       lp->sl_name[1] = lang[1];
-       hash_init(&lp->sl_fwords.wi_ht);
-       ga_init2(&lp->sl_fwords.wi_add, sizeof(dword_T *), 4);
-       lp->sl_fwords.wi_addlen = 0;
-       hash_init(&lp->sl_kwords.wi_ht);
-       ga_init2(&lp->sl_kwords.wi_add, sizeof(dword_T *), 4);
-       lp->sl_kwords.wi_addlen = 0;
-       lp->sl_regions[0] = NUL;
-       lp->sl_block = NULL;
-
-       /* Find all spell files for "lang" in 'runtimepath' and load them.
-        * Use 'encoding', except that we use "latin1" for "latin9". */
-#ifdef FEAT_MBYTE
-       if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0)
-           p = p_enc;
-       else
-#endif
-           p = (char_u *)"latin1";
-       load_lp = lp;
-       sprintf((char *)fname_enc, "spell/%c%c.%s.spl", lang[0], lang[1], p);
-       r = do_in_runtimepath(fname_enc, TRUE, spell_load_file);
-       if (r == FAIL)
-       {
-           /* Try again to find an ASCII spell file. */
-           sprintf((char *)fname_ascii, "spell/%c%c.spl", lang[0], lang[1]);
-           r = do_in_runtimepath(fname_ascii, TRUE, spell_load_file);
-       }
-
-       if (r == FAIL)
-       {
-           vim_free(lp);
-           lp = NULL;
-           smsg((char_u *)_("Warning: Cannot find dictionary \"%s\""),
-                                                              fname_enc + 6);
-       }
-       else
-       {
-           lp->sl_next = first_lang;
-           first_lang = lp;
-       }
-    }
-
-    return lp;
-}
-
-/*
- * Load one spell file into "load_lp".
- * Invoked through do_in_runtimepath().
- */
-    static void
-spell_load_file(fname)
-    char_u     *fname;
-{
-    int                fd;
-    size_t     len;
-    int                l;
-    char_u     *p = NULL, *np;
-    sblock_T   *bl = NULL;
-    int                bl_used = 0;
-    size_t     rest = 0;
-    char_u     *rbuf;          /* read buffer */
-    char_u     *rbuf_end;      /* past last valid char in "rbuf" */
-    hash_T     hash;
-    hashitem_T *hi;
-    int                c;
-    int                cc;
-    int                region = REGION_ALL;
-    int                wlen;
-    winfo_T    *wi;
-    dword_T    *dw, *edw = NULL;
-    nword_T    *nw = NULL;
-    int                flags;
-    char_u     *save_sourcing_name = sourcing_name;
-    linenr_T   save_sourcing_lnum = sourcing_lnum;
-
-    rbuf = alloc((unsigned)(SBLOCKSIZE + MAXWLEN + 1));
-    if (rbuf == NULL)
-       return;
-
-    fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
-    if (fd < 0)
-    {
-       EMSG2(_(e_notopen), fname);
-       goto theend;
-    }
-
-    sourcing_name = fname;
-    sourcing_lnum = 0;
-
-    /* Get the length of the whole file. */
-    len = lseek(fd, (off_t)0, SEEK_END);
-    lseek(fd, (off_t)0, SEEK_SET);
-
-    /*
-     * Read the file one block at a time.
-     * "rest" is the length of an incomplete line at the previous block.
-     * "p" points to the remainder.
-     */
-    while (len > 0)
-    {
-       /* Read a block from the file.  Prepend the remainder of the previous
-        * block, if any. */
-       if (rest > 0)
-       {
-           if (rest > MAXWLEN)     /* truncate long line (should be comment) */
-               rest = MAXWLEN;
-           mch_memmove(rbuf, p, rest);
-           --sourcing_lnum;
-       }
-       if (len > SBLOCKSIZE)
-           l = SBLOCKSIZE;
-       else
-           l = len;
-       len -= l;
-       if (read(fd, rbuf + rest, l) != l)
-       {
-           EMSG2(_(e_notread), fname);
-           break;
-       }
-       rbuf_end = rbuf + l + rest;
-       rest = 0;
-
-       /* Deal with each line that was read until we finish the block. */
-       for (p = rbuf; p < rbuf_end; p = np)
-       {
-           ++sourcing_lnum;
-
-           /* "np" points to the first char after the line (CR, NL or white
-            * space). */
-           for (np = p; np < rbuf_end && *np >= ' '; mb_ptr_adv(np))
-               ;
-           if (np >= rbuf_end)
-           {
-               /* Incomplete line or end of file. */
-               rest = np - p;
-               if (len == 0)
-                   EMSG(_("E751: Truncated spell file"));
-               break;
-           }
-           *np = NUL;      /* terminate the line with a NUL */
-
-           if (*p == '-')
-           {
-               /*
-                * Region marker: ---, -xx, -xx-yy, etc.
-                */
-               ++p;
-               if (*p == '-')
-               {
-                   if (p[1] != '-' || p[2] != NUL)
-                   {
-                       EMSG2(_(e_invchar2), p - 1);
-                       len = 0;
-                       break;
-                   }
-                   region = REGION_ALL;
-               }
-               else
-               {
-                   char_u      *rp = load_lp->sl_regions;
-                   int         r;
-
-                   /* Start of a region.  The region may be repeated:
-                    * "-ca-uk".  Fill "region" with the bit mask for the
-                    * ones we find. */
-                   region = 0;
-                   for (;;)
-                   {
-                       r = find_region(rp, p);
-                       if (r == REGION_ALL)
-                       {
-                           /* new region, add it to sl_regions[] */
-                           r = STRLEN(rp);
-                           if (r >= 16)
-                           {
-                               EMSG2(_("E752: Too many regions: %s"), p);
-                               len = 0;
-                               break;
-                           }
-                           else
-                           {
-                               rp[r] = p[0];
-                               rp[r + 1] = p[1];
-                               rp[r + 2] = NUL;
-                               r = 1 << (r / 2);
-                           }
-                       }
-                       else
-                           r = 1 << r;
-
-                       region |= r;
-                       if (p[2] != '-')
-                       {
-                           if (p[2] > ' ')
-                           {
-                               EMSG2(_(e_invchar2), p - 1);
-                               len = 0;
-                           }
-                           break;
-                       }
-                       p += 3;
-                   }
-               }
-           }
-           else if (*p != '#' && *p != NUL)
-           {
-               /*
-                * Not an empty line or comment.
-                */
-               if (*p == '!')
-               {
-                   wi = &load_lp->sl_kwords;       /* keep case */
-                   ++p;
-               }
-               else
-                   wi = &load_lp->sl_fwords;       /* fold case */
-
-               flags = 0;
-               c = *p;
-               if (c == '>')           /* rare word */
-               {
-                   flags = DW_RARE;
-                   ++p;
-               }
-               else if (*p == '+')     /* addition */
-                   ++p;
-
-               if (c != '+' && !spell_iswordc(p))
-               {
-                   EMSG2(_(e_invchar2), p);
-                   len = 0;
-                   break;
-               }
-
-               /* Make sure there is room for the word.  Folding case may
-                * double the size. */
-               wlen = np - p;
-               if (bl == NULL || bl_used + sizeof(dword_T) + wlen
-#ifdef FEAT_MBYTE
-                                           * (has_mbyte ? 2 : 1)
-#endif
-                                                           >= SBLOCKSIZE)
-               {
-                   /* Allocate a block of memory to store the dword_T in.
-                    * This is not freed until spell_reload() is called. */
-                   bl = (sblock_T *)alloc((unsigned)(sizeof(sblock_T)
-                                                          + SBLOCKSIZE));
-                   if (bl == NULL)
-                   {
-                       len = 0;
-                       break;
-                   }
-                   bl->sb_next = load_lp->sl_block;
-                   load_lp->sl_block = bl;
-                   bl_used = 0;
-               }
-               dw = (dword_T *)(bl->sb_data + bl_used);
-
-               /* For fold-case words fold the case and check for start
-                * with uppercase letter. */
-               if (wi == &load_lp->sl_fwords)
-               {
-#ifdef FEAT_MBYTE
-                   if (MB_ISUPPER(mb_ptr2char(p)))
-#else
-                   if (MB_ISUPPER(*p))
-#endif
-                       flags |= DW_CAP;
-
-                   /* Fold case. */
-                   (void)str_foldcase(p, np - p, dw->dw_word, wlen
-#ifdef FEAT_MBYTE
-                                                    * (has_mbyte ? 2 : 1)
-#endif
-                                                                    + 1);
-#ifdef FEAT_MBYTE
-                   /* case folding may change length of word */
-                   wlen = STRLEN(dw->dw_word);
-#endif
-               }
-               else
-               {
-                   /* Keep case: copy the word as-is. */
-                   mch_memmove(dw->dw_word, p, wlen + 1);
-               }
-
-               if (c == '+')
-               {
-                   garray_T    *gap = &wi->wi_add;
-
-                   /* Addition.  TODO: search for matching entry? */
-                   if (wi->wi_addlen < wlen)
-                       wi->wi_addlen = wlen;
-                   if (ga_grow(gap, 1) == FAIL)
-                   {
-                       len = 0;
-                       break;
-                   }
-                   *(((dword_T **)gap->ga_data) + gap->ga_len) = dw;
-                   ++gap->ga_len;
-                   dw->dw_region = region;
-                   dw->dw_flags = flags;
-                   bl_used += sizeof(dword_T) + wlen;
-               }
-               else
-               {
-                   /*
-                    * Check for a non-word character.  If found it's
-                    * going to be an nword.
-                    * For an nword we split in two: the leading dword and
-                    * the remainder.  The dword goes in the hashtable
-                    * with an nword_T, the remainder is put in the
-                    * dword_T (starting with the first non-word
-                    * character).
-                    */
-                   cc = NUL;
-                   for (p = dw->dw_word; *p != NUL; mb_ptr_adv(p))
-                       if (!spell_iswordc(p))
-                       {
-                           cc = *p;
-                           *p = NUL;
-                           break;
-                       }
-
-                   /* check if we already have this dword */
-                   hash = hash_hash(dw->dw_word);
-                   hi = hash_lookup(&wi->wi_ht, dw->dw_word, hash);
-                   if (!HASHITEM_EMPTY(hi))
-                   {
-                       /* Existing entry. */
-                       edw = HI2DWORD(hi);
-                       if ((edw->dw_flags & (DW_CAP | DW_RARE))
-                                  == (dw->dw_flags & (DW_CAP | DW_RARE)))
-                       {
-                           if (p_verbose > 0)
-                               smsg((char_u *)_("Warning: duplicate word \"%s\" in %s"),
-                                                     dw->dw_word, fname);
-                       }
-                   }
-
-                   if (cc != NUL) /* nword */
-                   {
-                       if (HASHITEM_EMPTY(hi)
-                                      || (edw->dw_flags & DW_NWORD) == 0)
-                       {
-                           sblock_T *sb;
-
-                           /* Need to allocate a new nword_T.  Put it in an
-                            * sblock_T, so that we can free it later. */
-                           sb = (sblock_T *)alloc(
-                                   (unsigned)(sizeof(sblock_T)
-                                              + sizeof(nword_T) + wlen));
-                           if (sb == NULL)
-                           {
-                               len = 0;
-                               break;
-                           }
-                           sb->sb_next = load_lp->sl_block;
-                           load_lp->sl_block = sb;
-                           nw = (nword_T *)sb->sb_data;
-
-                           ga_init2(&nw->nw_ga, sizeof(dword_T *), 4);
-                           nw->nw_maxlen = 0;
-                           STRCPY(nw->nw_word, dw->dw_word);
-                           if (!HASHITEM_EMPTY(hi))
-                           {
-                               /* Note: the nw_region and nw_flags is for
-                                * the dword that matches with the start
-                                * of this nword, not for the nword
-                                * itself! */
-                               nw->nw_region = edw->dw_region;
-                               nw->nw_flags = edw->dw_flags | DW_NWORD;
-
-                               /* Remove the dword item so that we can
-                                * add it as an nword. */
-                               hash_remove(&wi->wi_ht, hi);
-                               hi = hash_lookup(&wi->wi_ht,
-                                                      nw->nw_word, hash);
-                           }
-                           else
-                           {
-                               nw->nw_region = 0;
-                               nw->nw_flags = DW_NWORD;
-                           }
-                       }
-                       else
-                           nw = HI2NWORD(hi);
-                   }
-
-                   if (HASHITEM_EMPTY(hi))
-                   {
-                       /* Add new dword or nword entry. */
-                       hash_add_item(&wi->wi_ht, hi, cc == NUL
-                                      ? dw->dw_word : nw->nw_word, hash);
-                       if (cc == NUL)
-                       {
-                           /* New dword: init the values and count the
-                            * used space.  */
-                           dw->dw_flags = DW_DWORD | flags;
-                           dw->dw_region = region;
-                           bl_used += sizeof(dword_T) + wlen;
-                       }
-                   }
-                   else if (cc == NUL)
-                   {
-                       /* existing dword: add the region and flags */
-                       dw = edw;
-                       dw->dw_region |= region;
-                       dw->dw_flags |= DW_DWORD | flags;
-                   }
-
-                   if (cc != NUL)
-                   {
-                       /* Use the dword for the non-word character and
-                        * following characters. */
-                       dw->dw_region = region;
-                       dw->dw_flags = flags;
-                       STRCPY(dw->dw_word + 1, p + 1);
-                       dw->dw_word[0] = cc;
-                       l = wlen - (p - dw->dw_word);
-                       bl_used += sizeof(dword_T) + l;
-                       if (nw->nw_maxlen < l)
-                           nw->nw_maxlen = l;
-
-                       /* Add the dword to the growarray in the nword. */
-                       if (ga_grow(&nw->nw_ga, 1) == FAIL)
-                       {
-                           len = 0;
-                           break;
-                       }
-                       *((dword_T **)nw->nw_ga.ga_data + nw->nw_ga.ga_len)
-                                                                    = dw;
-                       ++nw->nw_ga.ga_len;
-                   }
-               }
-           }
-
-           /* Skip over CR and NL characters and trailing white space. */
-           while (np < rbuf_end && *np <= ' ')
-               ++np;
-       }
-    }
-
-    close(fd);
-theend:
-    sourcing_name = save_sourcing_name;
-    sourcing_lnum = save_sourcing_lnum;
-    vim_free(rbuf);
-}
-
-
-#endif
+#endif  /* FEAT_SYN_HL */