comparison src/spell.c @ 310:04bf54c587f4

updated for version 7.0082
author vimboss
date Tue, 07 Jun 2005 21:00:02 +0000
parents 7010607c5753
children 96789bc4346a
comparison
equal deleted inserted replaced
309:ba02e70f9b18 310:04bf54c587f4
149 typedef struct slang_S slang_T; 149 typedef struct slang_S slang_T;
150 struct slang_S 150 struct slang_S
151 { 151 {
152 slang_T *sl_next; /* next language */ 152 slang_T *sl_next; /* next language */
153 char_u *sl_name; /* language name "en", "en.rare", "nl", etc. */ 153 char_u *sl_name; /* language name "en", "en.rare", "nl", etc. */
154 char_u *sl_fname; /* name of .spl file */
155 int sl_add; /* TRUE if it's an addition. */
154 char_u *sl_fbyts; /* case-folded word bytes */ 156 char_u *sl_fbyts; /* case-folded word bytes */
155 int *sl_fidxs; /* case-folded word indexes */ 157 int *sl_fidxs; /* case-folded word indexes */
156 char_u *sl_kbyts; /* keep-case word bytes */ 158 char_u *sl_kbyts; /* keep-case word bytes */
157 int *sl_kidxs; /* keep-case word indexes */ 159 int *sl_kidxs; /* keep-case word indexes */
158 char_u *sl_try; /* "TRY" from .aff file TODO: not used */ 160 char_u *sl_try; /* "TRY" from .aff file TODO: not used */
246 # define SPELL_ISWORDP(p) (spelltab.st_isw[*(p)]) 248 # define SPELL_ISWORDP(p) (spelltab.st_isw[*(p)])
247 #endif 249 #endif
248 250
249 static slang_T *slang_alloc __ARGS((char_u *lang)); 251 static slang_T *slang_alloc __ARGS((char_u *lang));
250 static void slang_free __ARGS((slang_T *lp)); 252 static void slang_free __ARGS((slang_T *lp));
253 static void slang_clear __ARGS((slang_T *lp));
251 static void find_word __ARGS((matchinf_T *mip, int keepcap)); 254 static void find_word __ARGS((matchinf_T *mip, int keepcap));
252 static void spell_load_lang __ARGS((char_u *lang)); 255 static void spell_load_lang __ARGS((char_u *lang));
253 static void spell_load_file __ARGS((char_u *fname, void *cookie)); 256 static char_u *spell_enc __ARGS((void));
257 static void spell_load_cb __ARGS((char_u *fname, void *cookie));
258 static void spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp));
254 static int read_tree __ARGS((FILE *fd, char_u *byts, int *idxs, int maxidx, int startidx)); 259 static int read_tree __ARGS((FILE *fd, char_u *byts, int *idxs, int maxidx, int startidx));
255 static int find_region __ARGS((char_u *rp, char_u *region)); 260 static int find_region __ARGS((char_u *rp, char_u *region));
256 static int captype __ARGS((char_u *word, char_u *end)); 261 static int captype __ARGS((char_u *word, char_u *end));
262 static void spell_reload_one __ARGS((char_u *fname));
257 static int set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp)); 263 static int set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp));
258 #ifdef FEAT_MBYTE
259 static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp)); 264 static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp));
260 static void write_spell_chartab __ARGS((FILE *fd)); 265 static void write_spell_chartab __ARGS((FILE *fd));
261 #endif
262 static int spell_isupper __ARGS((int c)); 266 static int spell_isupper __ARGS((int c));
263 static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen)); 267 static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen));
264 268
265 static char *e_format = N_("E759: Format error in spell file"); 269 static char *e_format = N_("E759: Format error in spell file");
266 270
631 int len; 635 int len;
632 int has_syntax = syntax_present(curbuf); 636 int has_syntax = syntax_present(curbuf);
633 int col; 637 int col;
634 int can_spell; 638 int can_spell;
635 639
636 if (!curwin->w_p_spell || *curwin->w_buffer->b_p_spl == NUL) 640 if (!curwin->w_p_spell || *curbuf->b_p_spl == NUL)
637 { 641 {
638 EMSG(_("E756: Spell checking not enabled")); 642 EMSG(_("E756: Spell checking not enabled"));
639 return FAIL; 643 return FAIL;
640 } 644 }
641 645
744 return FAIL; /* interrupted */ 748 return FAIL; /* interrupted */
745 } 749 }
746 750
747 /* 751 /*
748 * Load word list(s) for "lang" from Vim spell file(s). 752 * Load word list(s) for "lang" from Vim spell file(s).
749 * "lang" must be the language without the region: "en". 753 * "lang" must be the language without the region: e.g., "en".
750 */ 754 */
751 static void 755 static void
752 spell_load_lang(lang) 756 spell_load_lang(lang)
753 char_u *lang; 757 char_u *lang;
754 { 758 {
755 char_u fname_enc[80]; 759 char_u fname_enc[85];
756 char_u *p;
757 int r; 760 int r;
758 char_u langcp[MAXWLEN + 1]; 761 char_u langcp[MAXWLEN + 1];
759 762
760 /* Copy the language name to pass it to spell_load_file() as a cookie. 763 /* Copy the language name to pass it to spell_load_cb() as a cookie.
761 * It's truncated when an error is detected. */ 764 * It's truncated when an error is detected. */
762 STRCPY(langcp, lang); 765 STRCPY(langcp, lang);
763 766
764 /* Find all spell files for "lang" in 'runtimepath' and load them. 767 /*
765 * Use 'encoding', except that we use "latin1" for "latin9". */ 768 * Find the first spell file for "lang" in 'runtimepath' and load it.
766 #ifdef FEAT_MBYTE 769 */
767 if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) 770 vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
768 p = p_enc; 771 "spell/%s.%s.spl", lang, spell_enc());
769 else 772 r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &langcp);
770 #endif
771 p = (char_u *)"latin1";
772 vim_snprintf((char *)fname_enc, sizeof(fname_enc),
773 "spell/%s.%s.spl", lang, p);
774 r = do_in_runtimepath(fname_enc, TRUE, spell_load_file, &langcp);
775 773
776 if (r == FAIL && *langcp != NUL) 774 if (r == FAIL && *langcp != NUL)
777 { 775 {
778 /* Try loading the ASCII version. */ 776 /* Try loading the ASCII version. */
779 vim_snprintf((char *)fname_enc, sizeof(fname_enc), 777 vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
780 "spell/%s.ascii.spl", lang); 778 "spell/%s.ascii.spl", lang);
781 r = do_in_runtimepath(fname_enc, TRUE, spell_load_file, &langcp); 779 r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &langcp);
782 } 780 }
783 781
784 if (r == FAIL) 782 if (r == FAIL)
785 smsg((char_u *)_("Warning: Cannot find word list \"%s\""), 783 smsg((char_u *)_("Warning: Cannot find word list \"%s\""),
786 fname_enc + 6); 784 fname_enc + 6);
785 else if (*langcp != NUL)
786 {
787 /* Load all the additions. */
788 STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
789 do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &langcp);
790 }
791 }
792
793 /*
794 * Return the encoding used for spell checking: Use 'encoding', except that we
795 * use "latin1" for "latin9". And limit to 60 characters (just in case).
796 */
797 static char_u *
798 spell_enc()
799 {
800
801 #ifdef FEAT_MBYTE
802 if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0)
803 return p_enc;
804 #endif
805 return (char_u *)"latin1";
787 } 806 }
788 807
789 /* 808 /*
790 * Allocate a new slang_T. 809 * Allocate a new slang_T.
791 * Caller must fill "sl_next". 810 * Caller must fill "sl_next".
811 static void 830 static void
812 slang_free(lp) 831 slang_free(lp)
813 slang_T *lp; 832 slang_T *lp;
814 { 833 {
815 vim_free(lp->sl_name); 834 vim_free(lp->sl_name);
835 vim_free(lp->sl_fname);
836 slang_clear(lp);
837 vim_free(lp);
838 }
839
840 /*
841 * Clear an slang_T so that the file can be reloaded.
842 */
843 static void
844 slang_clear(lp)
845 slang_T *lp;
846 {
816 vim_free(lp->sl_fbyts); 847 vim_free(lp->sl_fbyts);
848 lp->sl_fbyts = NULL;
817 vim_free(lp->sl_kbyts); 849 vim_free(lp->sl_kbyts);
850 lp->sl_kbyts = NULL;
818 vim_free(lp->sl_fidxs); 851 vim_free(lp->sl_fidxs);
852 lp->sl_fidxs = NULL;
819 vim_free(lp->sl_kidxs); 853 vim_free(lp->sl_kidxs);
854 lp->sl_kidxs = NULL;
820 ga_clear(&lp->sl_rep); 855 ga_clear(&lp->sl_rep);
821 vim_free(lp->sl_try); 856 vim_free(lp->sl_try);
822 vim_free(lp); 857 lp->sl_try = NULL;
823 } 858 }
824 859
825 /* 860 /*
826 * Load one spell file and store the info into a slang_T. 861 * Load one spell file and store the info into a slang_T.
827 * Invoked through do_in_runtimepath(). 862 * Invoked through do_in_runtimepath().
828 */ 863 */
829 static void 864 static void
830 spell_load_file(fname, cookie) 865 spell_load_cb(fname, cookie)
831 char_u *fname; 866 char_u *fname;
832 void *cookie; /* points to the language name */ 867 void *cookie; /* points to the language name */
833 { 868 {
834 char_u *lang = cookie; 869 spell_load_file(fname, (char_u *)cookie, NULL);
870 }
871
872 /*
873 * Load one spell file and store the info into a slang_T.
874 *
875 * This is invoked in two ways:
876 * - From spell_load_cb() to load a spell file for the first time. "lang" is
877 * the language name, "old_lp" is NULL. Will allocate an slang_T.
878 * - To reload a spell file that was changed. "lang" is NULL and "old_lp"
879 * points to the existing slang_T.
880 */
881 static void
882 spell_load_file(fname, lang, old_lp)
883 char_u *fname;
884 char_u *lang;
885 slang_T *old_lp;
886 {
835 FILE *fd; 887 FILE *fd;
836 char_u buf[MAXWLEN + 1]; 888 char_u buf[MAXWLEN + 1];
837 char_u *p; 889 char_u *p;
838 int i; 890 int i;
839 int len; 891 int len;
842 linenr_T save_sourcing_lnum = sourcing_lnum; 894 linenr_T save_sourcing_lnum = sourcing_lnum;
843 int cnt, ccnt; 895 int cnt, ccnt;
844 char_u *fol; 896 char_u *fol;
845 slang_T *lp = NULL; 897 slang_T *lp = NULL;
846 898
847 fd = fopen((char *)fname, "r"); 899 fd = mch_fopen((char *)fname, "r");
848 if (fd == NULL) 900 if (fd == NULL)
849 { 901 {
850 EMSG2(_(e_notopen), fname); 902 EMSG2(_(e_notopen), fname);
851 goto endFAIL; 903 goto endFAIL;
852 } 904 }
853 905 if (p_verbose > 2)
854 lp = slang_alloc(lang); 906 {
855 if (lp == NULL) 907 verbose_enter();
856 goto endFAIL; 908 smsg((char_u *)_("Reading spell file \"%s\""), fname);
909 verbose_leave();
910 }
911
912 if (old_lp == NULL)
913 {
914 lp = slang_alloc(lang);
915 if (lp == NULL)
916 goto endFAIL;
917
918 /* Remember the file name, used to reload the file when it's updated. */
919 lp->sl_fname = vim_strsave(fname);
920 if (lp->sl_fname == NULL)
921 goto endFAIL;
922
923 /* Check for .add.spl. */
924 lp->sl_add = strstr((char *)gettail(fname), ".add.") != NULL;
925 }
926 else
927 lp = old_lp;
857 928
858 /* Set sourcing_name, so that error messages mention the file name. */ 929 /* Set sourcing_name, so that error messages mention the file name. */
859 sourcing_name = fname; 930 sourcing_name = fname;
860 sourcing_lnum = 0; 931 sourcing_lnum = 0;
861 932
976 if (i < 0) 1047 if (i < 0)
977 goto formerr; 1048 goto formerr;
978 } 1049 }
979 } 1050 }
980 1051
981 lp->sl_next = first_lang; 1052 /* For a new file link it in the list of spell files. */
982 first_lang = lp; 1053 if (old_lp == NULL)
1054 {
1055 lp->sl_next = first_lang;
1056 first_lang = lp;
1057 }
983 1058
984 goto endOK; 1059 goto endOK;
985 1060
986 endFAIL: 1061 endFAIL:
987 /* truncating the name signals the error to spell_load_lang() */ 1062 if (lang != NULL)
988 *lang = NUL; 1063 /* truncating the name signals the error to spell_load_lang() */
989 if (lp != NULL) 1064 *lang = NUL;
1065 if (lp != NULL && old_lp == NULL)
990 slang_free(lp); 1066 slang_free(lp);
991 1067
992 endOK: 1068 endOK:
993 if (fd != NULL) 1069 if (fd != NULL)
994 fclose(fd); 1070 fclose(fd);
1141 * Loop over the languages, there can be several files for each. 1217 * Loop over the languages, there can be several files for each.
1142 */ 1218 */
1143 for (lp = first_lang; lp != NULL; lp = lp->sl_next) 1219 for (lp = first_lang; lp != NULL; lp = lp->sl_next)
1144 if (STRNICMP(lp->sl_name, lang, 2) == 0) 1220 if (STRNICMP(lp->sl_name, lang, 2) == 0)
1145 { 1221 {
1146 if (region == NULL) 1222 if (region == NULL || lp->sl_add)
1147 region_mask = REGION_ALL; 1223 region_mask = REGION_ALL;
1148 else 1224 else
1149 { 1225 {
1150 /* find region in sl_regions */ 1226 /* find region in sl_regions */
1151 c = find_region(lp->sl_regions, region); 1227 c = find_region(lp->sl_regions, region);
1235 /* find first letter */ 1311 /* find first letter */
1236 for (p = word; !SPELL_ISWORDP(p); mb_ptr_adv(p)) 1312 for (p = word; !SPELL_ISWORDP(p); mb_ptr_adv(p))
1237 if (p >= end) 1313 if (p >= end)
1238 return 0; /* only non-word characters, illegal word */ 1314 return 0; /* only non-word characters, illegal word */
1239 #ifdef FEAT_MBYTE 1315 #ifdef FEAT_MBYTE
1240 c = mb_ptr2char_adv(&p); 1316 if (has_mbyte)
1241 #else 1317 c = mb_ptr2char_adv(&p);
1242 c = *p++; 1318 else
1243 #endif 1319 #endif
1320 c = *p++;
1244 firstcap = allcap = spell_isupper(c); 1321 firstcap = allcap = spell_isupper(c);
1245 1322
1246 /* 1323 /*
1247 * Need to check all letters to find a word with mixed upper/lower. 1324 * Need to check all letters to find a word with mixed upper/lower.
1248 * But a word with an upper char only at start is a ONECAP. 1325 * But a word with an upper char only at start is a ONECAP.
1305 did_set_spelllang(buf); 1382 did_set_spelllang(buf);
1306 } 1383 }
1307 } 1384 }
1308 # endif 1385 # endif
1309 1386
1310 1387 /*
1311 #if defined(FEAT_MBYTE) || defined(PROTO) 1388 * Reload the spell file "fname" if it's loaded.
1389 */
1390 static void
1391 spell_reload_one(fname)
1392 char_u *fname;
1393 {
1394 slang_T *lp;
1395
1396 for (lp = first_lang; lp != NULL; lp = lp->sl_next)
1397 if (fullpathcmp(fname, lp->sl_fname, FALSE) == FPC_SAME)
1398 {
1399 slang_clear(lp);
1400 spell_load_file(fname, NULL, lp);
1401 redraw_all_later(NOT_VALID);
1402 }
1403 }
1404
1405
1312 /* 1406 /*
1313 * Functions for ":mkspell". 1407 * Functions for ":mkspell".
1314 * Only possible with the multi-byte feature.
1315 */ 1408 */
1316 1409
1317 #define MAXLINELEN 500 /* Maximum length in bytes of a line in a .aff 1410 #define MAXLINELEN 500 /* Maximum length in bytes of a line in a .aff
1318 and .dic file. */ 1411 and .dic file. */
1319 /* 1412 /*
1321 */ 1414 */
1322 typedef struct afffile_S 1415 typedef struct afffile_S
1323 { 1416 {
1324 char_u *af_enc; /* "SET", normalized, alloc'ed string or NULL */ 1417 char_u *af_enc; /* "SET", normalized, alloc'ed string or NULL */
1325 char_u *af_try; /* "TRY" line in "af_enc" encoding */ 1418 char_u *af_try; /* "TRY" line in "af_enc" encoding */
1326 int af_rar; /* ID for rare word */ 1419 int af_rar; /* RAR ID for rare word */
1327 int af_huh; /* ID for keep-case word */ 1420 int af_kep; /* KEP ID for keep-case word */
1328 hashtab_T af_pref; /* hashtable for prefixes, affheader_T */ 1421 hashtab_T af_pref; /* hashtable for prefixes, affheader_T */
1329 hashtab_T af_suff; /* hashtable for suffixes, affheader_T */ 1422 hashtab_T af_suff; /* hashtable for suffixes, affheader_T */
1330 garray_T af_rep; /* list of repentry_T entries from REP lines */ 1423 garray_T af_rep; /* list of repentry_T entries from REP lines */
1331 } afffile_T; 1424 } afffile_T;
1332 1425
1393 { 1486 {
1394 wordnode_T *si_foldroot; /* tree with case-folded words */ 1487 wordnode_T *si_foldroot; /* tree with case-folded words */
1395 wordnode_T *si_keeproot; /* tree with keep-case words */ 1488 wordnode_T *si_keeproot; /* tree with keep-case words */
1396 sblock_T *si_blocks; /* memory blocks used */ 1489 sblock_T *si_blocks; /* memory blocks used */
1397 int si_ascii; /* handling only ASCII words */ 1490 int si_ascii; /* handling only ASCII words */
1491 int si_add; /* addition file */
1398 int si_region; /* region mask */ 1492 int si_region; /* region mask */
1399 vimconv_T si_conv; /* for conversion to 'encoding' */ 1493 vimconv_T si_conv; /* for conversion to 'encoding' */
1400 int si_memtot; /* runtime memory used */ 1494 int si_memtot; /* runtime memory used */
1495 int si_verbose; /* verbose messages */
1401 } spellinfo_T; 1496 } spellinfo_T;
1402 1497
1403 static afffile_T *spell_read_aff __ARGS((char_u *fname, spellinfo_T *spin)); 1498 static afffile_T *spell_read_aff __ARGS((char_u *fname, spellinfo_T *spin));
1404 static int has_non_ascii __ARGS((char_u *s)); 1499 static int has_non_ascii __ARGS((char_u *s));
1405 static void spell_free_aff __ARGS((afffile_T *aff)); 1500 static void spell_free_aff __ARGS((afffile_T *aff));
1410 static char_u *getroom_save __ARGS((sblock_T **blp, char_u *s)); 1505 static char_u *getroom_save __ARGS((sblock_T **blp, char_u *s));
1411 static void free_blocks __ARGS((sblock_T *bl)); 1506 static void free_blocks __ARGS((sblock_T *bl));
1412 static wordnode_T *wordtree_alloc __ARGS((sblock_T **blp)); 1507 static wordnode_T *wordtree_alloc __ARGS((sblock_T **blp));
1413 static int store_word __ARGS((char_u *word, spellinfo_T *spin, int flags)); 1508 static int store_word __ARGS((char_u *word, spellinfo_T *spin, int flags));
1414 static int tree_add_word __ARGS((char_u *word, wordnode_T *tree, int flags, int region, sblock_T **blp)); 1509 static int tree_add_word __ARGS((char_u *word, wordnode_T *tree, int flags, int region, sblock_T **blp));
1415 static void wordtree_compress __ARGS((wordnode_T *root)); 1510 static void wordtree_compress __ARGS((wordnode_T *root, spellinfo_T *spin));
1416 static int node_compress __ARGS((wordnode_T *node, hashtab_T *ht, int *tot)); 1511 static int node_compress __ARGS((wordnode_T *node, hashtab_T *ht, int *tot));
1417 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2)); 1512 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
1418 static void write_vim_spell __ARGS((char_u *fname, spellinfo_T *spin, int regcount, char_u *regchars)); 1513 static void write_vim_spell __ARGS((char_u *fname, spellinfo_T *spin, int regcount, char_u *regchars));
1419 static int put_tree __ARGS((FILE *fd, wordnode_T *node, int index, int regionmask)); 1514 static int put_tree __ARGS((FILE *fd, wordnode_T *node, int index, int regionmask));
1515 static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int overwrite, int verbose));
1516 static void init_spellfile __ARGS((void));
1420 1517
1421 /* 1518 /*
1422 * Read an affix ".aff" file. 1519 * Read an affix ".aff" file.
1423 * Returns an afffile_T, NULL for failure. 1520 * Returns an afffile_T, NULL for failure.
1424 */ 1521 */
1445 static char *e_affname = N_("Affix name too long in %s line %d: %s"); 1542 static char *e_affname = N_("Affix name too long in %s line %d: %s");
1446 1543
1447 /* 1544 /*
1448 * Open the file. 1545 * Open the file.
1449 */ 1546 */
1450 fd = fopen((char *)fname, "r"); 1547 fd = mch_fopen((char *)fname, "r");
1451 if (fd == NULL) 1548 if (fd == NULL)
1452 { 1549 {
1453 EMSG2(_(e_notopen), fname); 1550 EMSG2(_(e_notopen), fname);
1454 return NULL; 1551 return NULL;
1455 } 1552 }
1456 1553
1457 smsg((char_u *)_("Reading affix file %s..."), fname); 1554 if (spin->si_verbose || p_verbose > 2)
1458 out_flush(); 1555 {
1556 if (!spin->si_verbose)
1557 verbose_enter();
1558 smsg((char_u *)_("Reading affix file %s..."), fname);
1559 out_flush();
1560 if (!spin->si_verbose)
1561 verbose_leave();
1562 }
1459 1563
1460 /* 1564 /*
1461 * Allocate and init the afffile_T structure. 1565 * Allocate and init the afffile_T structure.
1462 */ 1566 */
1463 aff = (afffile_T *)getroom(&spin->si_blocks, sizeof(afffile_T)); 1567 aff = (afffile_T *)getroom(&spin->si_blocks, sizeof(afffile_T));
1479 if (*rline == '#') 1583 if (*rline == '#')
1480 continue; 1584 continue;
1481 1585
1482 /* Convert from "SET" to 'encoding' when needed. */ 1586 /* Convert from "SET" to 'encoding' when needed. */
1483 vim_free(pc); 1587 vim_free(pc);
1588 #ifdef FEAT_MBYTE
1484 if (spin->si_conv.vc_type != CONV_NONE) 1589 if (spin->si_conv.vc_type != CONV_NONE)
1485 { 1590 {
1486 pc = string_convert(&spin->si_conv, rline, NULL); 1591 pc = string_convert(&spin->si_conv, rline, NULL);
1487 if (pc == NULL) 1592 if (pc == NULL)
1488 { 1593 {
1491 continue; 1596 continue;
1492 } 1597 }
1493 line = pc; 1598 line = pc;
1494 } 1599 }
1495 else 1600 else
1601 #endif
1496 { 1602 {
1497 pc = NULL; 1603 pc = NULL;
1498 line = rline; 1604 line = rline;
1499 } 1605 }
1500 1606
1521 if (itemcnt > 0) 1627 if (itemcnt > 0)
1522 { 1628 {
1523 if (STRCMP(items[0], "SET") == 0 && itemcnt == 2 1629 if (STRCMP(items[0], "SET") == 0 && itemcnt == 2
1524 && aff->af_enc == NULL) 1630 && aff->af_enc == NULL)
1525 { 1631 {
1632 #ifdef FEAT_MBYTE
1526 /* Setup for conversion from "ENC" to 'encoding'. */ 1633 /* Setup for conversion from "ENC" to 'encoding'. */
1527 aff->af_enc = enc_canonize(items[1]); 1634 aff->af_enc = enc_canonize(items[1]);
1528 if (aff->af_enc != NULL && !spin->si_ascii 1635 if (aff->af_enc != NULL && !spin->si_ascii
1529 && convert_setup(&spin->si_conv, aff->af_enc, 1636 && convert_setup(&spin->si_conv, aff->af_enc,
1530 p_enc) == FAIL) 1637 p_enc) == FAIL)
1531 smsg((char_u *)_("Conversion in %s not supported: from %s to %s"), 1638 smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
1532 fname, aff->af_enc, p_enc); 1639 fname, aff->af_enc, p_enc);
1640 #else
1641 smsg((char_u *)_("Conversion in %s not supported"), fname);
1642 #endif
1533 } 1643 }
1534 else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1) 1644 else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1)
1535 { 1645 {
1536 /* ignored */ 1646 /* ignored */
1537 } 1647 }
1545 { 1655 {
1546 aff->af_rar = items[1][0]; 1656 aff->af_rar = items[1][0];
1547 if (items[1][1] != NUL) 1657 if (items[1][1] != NUL)
1548 smsg((char_u *)_(e_affname), fname, lnum, items[1]); 1658 smsg((char_u *)_(e_affname), fname, lnum, items[1]);
1549 } 1659 }
1550 else if (STRCMP(items[0], "HUH") == 0 && itemcnt == 2 1660 else if (STRCMP(items[0], "KEP") == 0 && itemcnt == 2
1551 && aff->af_huh == 0) 1661 && aff->af_kep == 0)
1552 { 1662 {
1553 aff->af_huh = items[1][0]; 1663 aff->af_kep = items[1][0];
1554 if (items[1][1] != NUL) 1664 if (items[1][1] != NUL)
1555 smsg((char_u *)_(e_affname), fname, lnum, items[1]); 1665 smsg((char_u *)_(e_affname), fname, lnum, items[1]);
1556 } 1666 }
1557 else if ((STRCMP(items[0], "PFX") == 0 1667 else if ((STRCMP(items[0], "PFX") == 0
1558 || STRCMP(items[0], "SFX") == 0) 1668 || STRCMP(items[0], "SFX") == 0)
1780 int flags; 1890 int flags;
1781 1891
1782 /* 1892 /*
1783 * Open the file. 1893 * Open the file.
1784 */ 1894 */
1785 fd = fopen((char *)fname, "r"); 1895 fd = mch_fopen((char *)fname, "r");
1786 if (fd == NULL) 1896 if (fd == NULL)
1787 { 1897 {
1788 EMSG2(_(e_notopen), fname); 1898 EMSG2(_(e_notopen), fname);
1789 return FAIL; 1899 return FAIL;
1790 } 1900 }
1791 1901
1792 /* The hashtable is only used to detect duplicated words. */ 1902 /* The hashtable is only used to detect duplicated words. */
1793 hash_init(&ht); 1903 hash_init(&ht);
1794 1904
1795 smsg((char_u *)_("Reading dictionary file %s..."), fname); 1905 if (spin->si_verbose || p_verbose > 2)
1796 out_flush(); 1906 {
1907 if (!spin->si_verbose)
1908 verbose_enter();
1909 smsg((char_u *)_("Reading dictionary file %s..."), fname);
1910 out_flush();
1911 if (!spin->si_verbose)
1912 verbose_leave();
1913 }
1797 1914
1798 /* Read and ignore the first line: word count. */ 1915 /* Read and ignore the first line: word count. */
1799 (void)vim_fgets(line, MAXLINELEN, fd); 1916 (void)vim_fgets(line, MAXLINELEN, fd);
1800 if (!isdigit(*skipwhite(line))) 1917 if (!isdigit(*skipwhite(line)))
1801 EMSG2(_("E760: No word count in %s"), fname); 1918 EMSG2(_("E760: No word count in %s"), fname);
1818 if (l == 0) 1935 if (l == 0)
1819 continue; /* empty line */ 1936 continue; /* empty line */
1820 line[l] = NUL; 1937 line[l] = NUL;
1821 1938
1822 /* This takes time, print a message now and then. */ 1939 /* This takes time, print a message now and then. */
1823 if ((lnum & 0x3ff) == 0) 1940 if (spin->si_verbose && (lnum & 0x3ff) == 0)
1824 { 1941 {
1825 vim_snprintf((char *)message, sizeof(message), 1942 vim_snprintf((char *)message, sizeof(message),
1826 _("line %6d - %s"), lnum, line); 1943 _("line %6d - %s"), lnum, line);
1827 msg_start(); 1944 msg_start();
1828 msg_outtrans_attr(message, 0); 1945 msg_outtrans_attr(message, 0);
1842 { 1959 {
1843 ++non_ascii; 1960 ++non_ascii;
1844 continue; 1961 continue;
1845 } 1962 }
1846 1963
1964 #ifdef FEAT_MBYTE
1847 /* Convert from "SET" to 'encoding' when needed. */ 1965 /* Convert from "SET" to 'encoding' when needed. */
1848 if (spin->si_conv.vc_type != CONV_NONE) 1966 if (spin->si_conv.vc_type != CONV_NONE)
1849 { 1967 {
1850 pc = string_convert(&spin->si_conv, line, NULL); 1968 pc = string_convert(&spin->si_conv, line, NULL);
1851 if (pc == NULL) 1969 if (pc == NULL)
1855 continue; 1973 continue;
1856 } 1974 }
1857 w = pc; 1975 w = pc;
1858 } 1976 }
1859 else 1977 else
1978 #endif
1860 { 1979 {
1861 pc = NULL; 1980 pc = NULL;
1862 w = line; 1981 w = line;
1863 } 1982 }
1864 1983
1881 flags = 0; 2000 flags = 0;
1882 if (afflist != NULL) 2001 if (afflist != NULL)
1883 { 2002 {
1884 /* Check for affix name that stands for keep-case word and stands 2003 /* Check for affix name that stands for keep-case word and stands
1885 * for rare word (if defined). */ 2004 * for rare word (if defined). */
1886 if (affile->af_huh != NUL 2005 if (affile->af_kep != NUL
1887 && vim_strchr(afflist, affile->af_huh) != NULL) 2006 && vim_strchr(afflist, affile->af_kep) != NULL)
1888 flags |= WF_KEEPCAP; 2007 flags |= WF_KEEPCAP;
1889 if (affile->af_rar != NUL 2008 if (affile->af_rar != NUL
1890 && vim_strchr(afflist, affile->af_rar) != NULL) 2009 && vim_strchr(afflist, affile->af_rar) != NULL)
1891 flags |= WF_RARE; 2010 flags |= WF_RARE;
1892 } 2011 }
1981 *newword = NUL; 2100 *newword = NUL;
1982 else 2101 else
1983 STRCPY(newword, ae->ae_add); 2102 STRCPY(newword, ae->ae_add);
1984 p = word; 2103 p = word;
1985 if (ae->ae_chop != NULL) 2104 if (ae->ae_chop != NULL)
2105 {
1986 /* Skip chop string. */ 2106 /* Skip chop string. */
1987 for (i = mb_charlen(ae->ae_chop); i > 0; --i) 2107 #ifdef FEAT_MBYTE
2108 if (has_mbyte)
2109 i = mb_charlen(ae->ae_chop);
2110 else
2111 #endif
2112 i = STRLEN(ae->ae_chop);
2113 for ( ; i > 0; --i)
1988 mb_ptr_adv(p); 2114 mb_ptr_adv(p);
2115 }
1989 STRCAT(newword, p); 2116 STRCAT(newword, p);
1990 } 2117 }
1991 else 2118 else
1992 { 2119 {
1993 /* suffix: chop/add at the end of the word */ 2120 /* suffix: chop/add at the end of the word */
1994 STRCPY(newword, word); 2121 STRCPY(newword, word);
1995 if (ae->ae_chop != NULL) 2122 if (ae->ae_chop != NULL)
1996 { 2123 {
1997 /* Remove chop string. */ 2124 /* Remove chop string. */
1998 p = newword + STRLEN(newword); 2125 p = newword + STRLEN(newword);
1999 for (i = mb_charlen(ae->ae_chop); i > 0; --i) 2126 #ifdef FEAT_MBYTE
2127 if (has_mbyte)
2128 i = mb_charlen(ae->ae_chop);
2129 else
2130 #endif
2131 i = STRLEN(ae->ae_chop);
2132 for ( ; i > 0; --i)
2000 mb_ptr_back(newword, p); 2133 mb_ptr_back(newword, p);
2001 *p = NUL; 2134 *p = NUL;
2002 } 2135 }
2003 if (ae->ae_add != NULL) 2136 if (ae->ae_add != NULL)
2004 STRCAT(newword, ae->ae_add); 2137 STRCAT(newword, ae->ae_add);
2038 char_u *pc = NULL; 2171 char_u *pc = NULL;
2039 int l; 2172 int l;
2040 int retval = OK; 2173 int retval = OK;
2041 int did_word = FALSE; 2174 int did_word = FALSE;
2042 int non_ascii = 0; 2175 int non_ascii = 0;
2043 char_u *enc;
2044 int flags; 2176 int flags;
2045 2177
2046 /* 2178 /*
2047 * Open the file. 2179 * Open the file.
2048 */ 2180 */
2049 fd = fopen((char *)fname, "r"); 2181 fd = mch_fopen((char *)fname, "r");
2050 if (fd == NULL) 2182 if (fd == NULL)
2051 { 2183 {
2052 EMSG2(_(e_notopen), fname); 2184 EMSG2(_(e_notopen), fname);
2053 return FAIL; 2185 return FAIL;
2054 } 2186 }
2055 2187
2056 smsg((char_u *)_("Reading word file %s..."), fname); 2188 if (spin->si_verbose || p_verbose > 2)
2057 out_flush(); 2189 {
2190 if (!spin->si_verbose)
2191 verbose_enter();
2192 smsg((char_u *)_("Reading word file %s..."), fname);
2193 out_flush();
2194 if (!spin->si_verbose)
2195 verbose_leave();
2196 }
2058 2197
2059 /* 2198 /*
2060 * Read all the lines in the file one by one. 2199 * Read all the lines in the file one by one.
2061 */ 2200 */
2062 while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) 2201 while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int)
2076 continue; /* empty or blank line */ 2215 continue; /* empty or blank line */
2077 rline[l] = NUL; 2216 rline[l] = NUL;
2078 2217
2079 /* Convert from "=encoding={encoding}" to 'encoding' when needed. */ 2218 /* Convert from "=encoding={encoding}" to 'encoding' when needed. */
2080 vim_free(pc); 2219 vim_free(pc);
2220 #ifdef FEAT_MBYTE
2081 if (spin->si_conv.vc_type != CONV_NONE) 2221 if (spin->si_conv.vc_type != CONV_NONE)
2082 { 2222 {
2083 pc = string_convert(&spin->si_conv, rline, NULL); 2223 pc = string_convert(&spin->si_conv, rline, NULL);
2084 if (pc == NULL) 2224 if (pc == NULL)
2085 { 2225 {
2088 continue; 2228 continue;
2089 } 2229 }
2090 line = pc; 2230 line = pc;
2091 } 2231 }
2092 else 2232 else
2233 #endif
2093 { 2234 {
2094 pc = NULL; 2235 pc = NULL;
2095 line = rline; 2236 line = rline;
2096 } 2237 }
2097 2238
2108 else if (did_word) 2249 else if (did_word)
2109 smsg((char_u *)_("=encoding= line after word ignored in %s line %d: %s"), 2250 smsg((char_u *)_("=encoding= line after word ignored in %s line %d: %s"),
2110 fname, lnum, line); 2251 fname, lnum, line);
2111 else 2252 else
2112 { 2253 {
2254 #ifdef FEAT_MBYTE
2255 char_u *enc;
2256
2113 /* Setup for conversion to 'encoding'. */ 2257 /* Setup for conversion to 'encoding'. */
2114 enc = enc_canonize(line + 10); 2258 enc = enc_canonize(line + 10);
2115 if (enc != NULL && !spin->si_ascii 2259 if (enc != NULL && !spin->si_ascii
2116 && convert_setup(&spin->si_conv, enc, 2260 && convert_setup(&spin->si_conv, enc,
2117 p_enc) == FAIL) 2261 p_enc) == FAIL)
2118 smsg((char_u *)_("Conversion in %s not supported: from %s to %s"), 2262 smsg((char_u *)_("Conversion in %s not supported: from %s to %s"),
2119 fname, line + 10, p_enc); 2263 fname, line + 10, p_enc);
2120 vim_free(enc); 2264 vim_free(enc);
2265 #else
2266 smsg((char_u *)_("Conversion in %s not supported"), fname);
2267 #endif
2121 } 2268 }
2122 continue; 2269 continue;
2123 } 2270 }
2124 2271
2125 if (*line == '=') 2272 if (*line == '=')
2167 } 2314 }
2168 2315
2169 vim_free(pc); 2316 vim_free(pc);
2170 fclose(fd); 2317 fclose(fd);
2171 2318
2172 if (spin->si_ascii && non_ascii > 0) 2319 if (spin->si_ascii && non_ascii > 0 && (spin->si_verbose || p_verbose > 2))
2320 {
2321 if (p_verbose > 2)
2322 verbose_enter();
2173 smsg((char_u *)_("Ignored %d words with non-ASCII characters"), 2323 smsg((char_u *)_("Ignored %d words with non-ASCII characters"),
2174 non_ascii); 2324 non_ascii);
2325 if (p_verbose > 2)
2326 verbose_leave();
2327 }
2175 return retval; 2328 return retval;
2176 } 2329 }
2177 2330
2178 /* 2331 /*
2179 * Get part of an sblock_T, "len" bytes long. 2332 * Get part of an sblock_T, "len" bytes long.
2341 2494
2342 /* 2495 /*
2343 * Compress a tree: find tails that are identical and can be shared. 2496 * Compress a tree: find tails that are identical and can be shared.
2344 */ 2497 */
2345 static void 2498 static void
2346 wordtree_compress(root) 2499 wordtree_compress(root, spin)
2347 wordnode_T *root; 2500 wordnode_T *root;
2501 spellinfo_T *spin;
2348 { 2502 {
2349 hashtab_T ht; 2503 hashtab_T ht;
2350 int n; 2504 int n;
2351 int tot = 0; 2505 int tot = 0;
2352 2506
2353 if (root != NULL) 2507 if (root != NULL)
2354 { 2508 {
2355 hash_init(&ht); 2509 hash_init(&ht);
2356 n = node_compress(root, &ht, &tot); 2510 n = node_compress(root, &ht, &tot);
2357 smsg((char_u *)_("Compressed %d of %d nodes; %d%% remaining"), 2511 if (spin->si_verbose || p_verbose > 2)
2512 {
2513 if (!spin->si_verbose)
2514 verbose_enter();
2515 smsg((char_u *)_("Compressed %d of %d nodes; %d%% remaining"),
2358 n, tot, (tot - n) * 100 / tot); 2516 n, tot, (tot - n) * 100 / tot);
2517 if (p_verbose > 2)
2518 verbose_leave();
2519 }
2359 hash_clear(&ht); 2520 hash_clear(&ht);
2360 } 2521 }
2361 } 2522 }
2362 2523
2363 /* 2524 /*
2514 int regionmask; 2675 int regionmask;
2515 int round; 2676 int round;
2516 wordnode_T *tree; 2677 wordnode_T *tree;
2517 int nodecount; 2678 int nodecount;
2518 2679
2519 fd = fopen((char *)fname, "w"); 2680 fd = mch_fopen((char *)fname, "w");
2520 if (fd == NULL) 2681 if (fd == NULL)
2521 { 2682 {
2522 EMSG2(_(e_notopen), fname); 2683 EMSG2(_(e_notopen), fname);
2523 return; 2684 return;
2524 } 2685 }
2688 return newindex; 2849 return newindex;
2689 } 2850 }
2690 2851
2691 2852
2692 /* 2853 /*
2693 * ":mkspell outfile infile ..." 2854 * ":mkspell [-ascii] outfile infile ..."
2855 * ":mkspell [-ascii] addfile"
2694 */ 2856 */
2695 void 2857 void
2696 ex_mkspell(eap) 2858 ex_mkspell(eap)
2697 exarg_T *eap; 2859 exarg_T *eap;
2698 { 2860 {
2699 int fcount; 2861 int fcount;
2700 char_u **fnames; 2862 char_u **fnames;
2863 char_u *arg = eap->arg;
2864 int ascii = FALSE;
2865
2866 if (STRNCMP(arg, "-ascii", 6) == 0)
2867 {
2868 ascii = TRUE;
2869 arg = skipwhite(arg + 6);
2870 }
2871
2872 /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */
2873 if (get_arglist_exp(arg, &fcount, &fnames) == OK)
2874 {
2875 mkspell(fcount, fnames, ascii, eap->forceit, TRUE);
2876 FreeWild(fcount, fnames);
2877 }
2878 }
2879
2880 /*
2881 * Create a Vim spell file from one or more word lists.
2882 * "fnames[0]" is the output file name.
2883 * "fnames[fcount - 1]" is the last input file name.
2884 * Exception: when "fnames[0]" ends in ".add" it's used as the input file name
2885 * and ".spl" is appended to make the output file name.
2886 */
2887 static void
2888 mkspell(fcount, fnames, ascii, overwrite, verbose)
2889 int fcount;
2890 char_u **fnames;
2891 int ascii; /* -ascii argument given */
2892 int overwrite; /* overwrite existing output file */
2893 int verbose; /* give progress messages */
2894 {
2701 char_u fname[MAXPATHL]; 2895 char_u fname[MAXPATHL];
2702 char_u wfname[MAXPATHL]; 2896 char_u wfname[MAXPATHL];
2897 char_u **innames;
2898 int incount;
2703 afffile_T *(afile[8]); 2899 afffile_T *(afile[8]);
2704 int i; 2900 int i;
2705 int len; 2901 int len;
2706 char_u region_name[16]; 2902 char_u region_name[16];
2707 struct stat st; 2903 struct stat st;
2708 char_u *arg = eap->arg;
2709 int error = FALSE; 2904 int error = FALSE;
2710 spellinfo_T spin; 2905 spellinfo_T spin;
2711 2906
2712 vim_memset(&spin, 0, sizeof(spin)); 2907 vim_memset(&spin, 0, sizeof(spin));
2713 2908 spin.si_verbose = verbose;
2714 if (STRNCMP(arg, "-ascii", 6) == 0) 2909 spin.si_ascii = ascii;
2715 { 2910
2716 spin.si_ascii = TRUE; 2911 /* default: fnames[0] is output file, following are input files */
2717 arg = skipwhite(arg + 6); 2912 innames = &fnames[1];
2718 } 2913 incount = fcount - 1;
2719 2914
2720 /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */ 2915 if (fcount >= 1)
2721 if (get_arglist_exp(arg, &fcount, &fnames) == FAIL) 2916 {
2722 return; 2917 len = STRLEN(fnames[0]);
2723 if (fcount < 2) 2918 if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0)
2919 {
2920 /* For ":mkspell path/en.latin1.add" output file is
2921 * "path/en.latin1.add.spl". */
2922 innames = &fnames[0];
2923 incount = 1;
2924 vim_snprintf((char *)wfname, sizeof(wfname), "%s.spl", fnames[0]);
2925 }
2926 else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0)
2927 {
2928 /* Name ends in ".spl", use as the file name. */
2929 STRNCPY(wfname, fnames[0], sizeof(wfname));
2930 wfname[sizeof(wfname) - 1] = NUL;
2931 }
2932 else
2933 /* Name should be language, make the file name from it. */
2934 vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0],
2935 spin.si_ascii ? (char_u *)"ascii" : spell_enc());
2936
2937 /* Check for .ascii.spl. */
2938 if (strstr((char *)gettail(wfname), ".ascii.") != NULL)
2939 spin.si_ascii = TRUE;
2940
2941 /* Check for .add.spl. */
2942 if (strstr((char *)gettail(wfname), ".add.") != NULL)
2943 spin.si_add = TRUE;
2944 }
2945
2946 if (incount <= 0)
2724 EMSG(_(e_invarg)); /* need at least output and input names */ 2947 EMSG(_(e_invarg)); /* need at least output and input names */
2725 else if (fcount > 9) 2948 else if (incount > 8)
2726 EMSG(_("E754: Only up to 8 regions supported")); 2949 EMSG(_("E754: Only up to 8 regions supported"));
2727 else 2950 else
2728 { 2951 {
2729 /* Check for overwriting before doing things that may take a lot of 2952 /* Check for overwriting before doing things that may take a lot of
2730 * time. */ 2953 * time. */
2731 vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0], 2954 if (!overwrite && mch_stat((char *)wfname, &st) >= 0)
2732 spin.si_ascii ? (char_u *)"ascii" : p_enc);
2733 if (!eap->forceit && mch_stat((char *)wfname, &st) >= 0)
2734 { 2955 {
2735 EMSG(_(e_exists)); 2956 EMSG(_(e_exists));
2736 goto theend; 2957 return;
2737 } 2958 }
2738 if (mch_isdir(fnames[0])) 2959 if (mch_isdir(wfname))
2739 { 2960 {
2740 EMSG2(_(e_isadir2), fnames[0]); 2961 EMSG2(_(e_isadir2), wfname);
2741 goto theend; 2962 return;
2742 } 2963 }
2743 2964
2744 /* 2965 /*
2745 * Init the aff and dic pointers. 2966 * Init the aff and dic pointers.
2746 * Get the region names if there are more than 2 arguments. 2967 * Get the region names if there are more than 2 arguments.
2747 */ 2968 */
2748 for (i = 1; i < fcount; ++i) 2969 for (i = 0; i < incount; ++i)
2749 { 2970 {
2750 afile[i - 1] = NULL; 2971 afile[i] = NULL;
2751 2972
2752 if (fcount > 2) 2973 if (fcount > 2)
2753 { 2974 {
2754 len = STRLEN(fnames[i]); 2975 len = STRLEN(innames[i]);
2755 if (STRLEN(gettail(fnames[i])) < 5 || fnames[i][len - 3] != '_') 2976 if (STRLEN(gettail(innames[i])) < 5
2977 || innames[i][len - 3] != '_')
2756 { 2978 {
2757 EMSG2(_("E755: Invalid region in %s"), fnames[i]); 2979 EMSG2(_("E755: Invalid region in %s"), innames[i]);
2758 goto theend; 2980 return;
2759 } 2981 }
2760 else 2982 region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]);
2761 { 2983 region_name[i * 2 + 1] = TOLOWER_ASC(innames[i][len - 1]);
2762 region_name[(i - 1) * 2] = TOLOWER_ASC(fnames[i][len - 2]); 2984 }
2763 region_name[(i - 1) * 2 + 1] = 2985 }
2764 TOLOWER_ASC(fnames[i][len - 1]); 2986
2765 } 2987 if (!spin.si_add)
2766 } 2988 /* Clear the char type tables, don't want to use any of the
2767 } 2989 * currently used spell properties. */
2768 2990 init_spell_chartab();
2769 /* Clear the char type tables, don't want to use any of the currently
2770 * used spell properties. */
2771 init_spell_chartab();
2772 2991
2773 spin.si_foldroot = wordtree_alloc(&spin.si_blocks); 2992 spin.si_foldroot = wordtree_alloc(&spin.si_blocks);
2774 spin.si_keeproot = wordtree_alloc(&spin.si_blocks); 2993 spin.si_keeproot = wordtree_alloc(&spin.si_blocks);
2775 if (spin.si_foldroot == NULL || spin.si_keeproot == NULL) 2994 if (spin.si_foldroot == NULL || spin.si_keeproot == NULL)
2776 { 2995 {
2777 error = TRUE; 2996 error = TRUE;
2778 goto theend; 2997 return;
2779 } 2998 }
2780 2999
2781 /* 3000 /*
2782 * Read all the .aff and .dic files. 3001 * Read all the .aff and .dic files.
2783 * Text is converted to 'encoding'. 3002 * Text is converted to 'encoding'.
2784 * Words are stored in the case-folded and keep-case trees. 3003 * Words are stored in the case-folded and keep-case trees.
2785 */ 3004 */
2786 for (i = 1; i < fcount && !error; ++i) 3005 for (i = 0; i < incount && !error; ++i)
2787 { 3006 {
2788 spin.si_conv.vc_type = CONV_NONE; 3007 spin.si_conv.vc_type = CONV_NONE;
2789 spin.si_region = 1 << (i - 1); 3008 spin.si_region = 1 << i;
2790 3009
2791 vim_snprintf((char *)fname, sizeof(fname), "%s.aff", fnames[i]); 3010 vim_snprintf((char *)fname, sizeof(fname), "%s.aff", innames[i]);
2792 if (mch_stat((char *)fname, &st) >= 0) 3011 if (mch_stat((char *)fname, &st) >= 0)
2793 { 3012 {
2794 /* Read the .aff file. Will init "spin->si_conv" based on the 3013 /* Read the .aff file. Will init "spin->si_conv" based on the
2795 * "SET" line. */ 3014 * "SET" line. */
2796 afile[i - 1] = spell_read_aff(fname, &spin); 3015 afile[i] = spell_read_aff(fname, &spin);
2797 if (afile[i - 1] == NULL) 3016 if (afile[i] == NULL)
2798 error = TRUE; 3017 error = TRUE;
2799 else 3018 else
2800 { 3019 {
2801 /* Read the .dic file and store the words in the trees. */ 3020 /* Read the .dic file and store the words in the trees. */
2802 vim_snprintf((char *)fname, sizeof(fname), "%s.dic", 3021 vim_snprintf((char *)fname, sizeof(fname), "%s.dic",
2803 fnames[i]); 3022 innames[i]);
2804 if (spell_read_dic(fname, &spin, afile[i - 1]) == FAIL) 3023 if (spell_read_dic(fname, &spin, afile[i]) == FAIL)
2805 error = TRUE; 3024 error = TRUE;
2806 } 3025 }
2807 } 3026 }
2808 else 3027 else
2809 { 3028 {
2810 /* No .aff file, try reading the file as a word list. Store 3029 /* No .aff file, try reading the file as a word list. Store
2811 * the words in the trees. */ 3030 * the words in the trees. */
2812 if (spell_read_wordfile(fnames[i], &spin) == FAIL) 3031 if (spell_read_wordfile(innames[i], &spin) == FAIL)
2813 error = TRUE; 3032 error = TRUE;
2814 } 3033 }
2815 3034
3035 #ifdef FEAT_MBYTE
2816 /* Free any conversion stuff. */ 3036 /* Free any conversion stuff. */
2817 convert_setup(&spin.si_conv, NULL, NULL); 3037 convert_setup(&spin.si_conv, NULL, NULL);
3038 #endif
2818 } 3039 }
2819 3040
2820 if (!error) 3041 if (!error)
2821 { 3042 {
2822 /* 3043 /*
2826 spin.si_keeproot = spin.si_keeproot->wn_sibling; 3047 spin.si_keeproot = spin.si_keeproot->wn_sibling;
2827 3048
2828 /* 3049 /*
2829 * Combine tails in the tree. 3050 * Combine tails in the tree.
2830 */ 3051 */
2831 MSG(_("Compressing word tree...")); 3052 if (verbose || p_verbose > 2)
2832 out_flush(); 3053 {
2833 wordtree_compress(spin.si_foldroot); 3054 if (!verbose)
2834 wordtree_compress(spin.si_keeproot); 3055 verbose_enter();
3056 MSG(_("Compressing word tree..."));
3057 out_flush();
3058 if (!verbose)
3059 verbose_leave();
3060 }
3061 wordtree_compress(spin.si_foldroot, &spin);
3062 wordtree_compress(spin.si_keeproot, &spin);
2835 } 3063 }
2836 3064
2837 if (!error) 3065 if (!error)
2838 { 3066 {
2839 /* 3067 /*
2840 * Write the info in the spell file. 3068 * Write the info in the spell file.
2841 */ 3069 */
2842 smsg((char_u *)_("Writing spell file %s..."), wfname); 3070 if (verbose || p_verbose > 2)
2843 out_flush(); 3071 {
2844 write_vim_spell(wfname, &spin, fcount - 1, region_name); 3072 if (!verbose)
2845 MSG(_("Done!")); 3073 verbose_enter();
2846 3074 smsg((char_u *)_("Writing spell file %s..."), wfname);
2847 smsg((char_u *)_("Estimated runtime memory use: %d bytes"), 3075 out_flush();
3076 if (!verbose)
3077 verbose_leave();
3078 }
3079
3080 write_vim_spell(wfname, &spin, incount, region_name);
3081
3082 if (verbose || p_verbose > 2)
3083 {
3084 if (!verbose)
3085 verbose_enter();
3086 MSG(_("Done!"));
3087 smsg((char_u *)_("Estimated runtime memory use: %d bytes"),
2848 spin.si_memtot); 3088 spin.si_memtot);
2849 out_flush(); 3089 out_flush();
2850 3090 if (!verbose)
2851 /* May need to reload spell dictionaries */ 3091 verbose_leave();
2852 spell_reload(); 3092 }
3093
3094 /* If the file is loaded need to reload it. */
3095 spell_reload_one(wfname);
2853 } 3096 }
2854 3097
2855 /* Free the allocated memory. */ 3098 /* Free the allocated memory. */
2856 free_blocks(spin.si_blocks); 3099 free_blocks(spin.si_blocks);
2857 3100
2858 /* Free the .aff file structures. */ 3101 /* Free the .aff file structures. */
2859 for (i = 1; i < fcount; ++i) 3102 for (i = 0; i < incount; ++i)
2860 if (afile[i - 1] != NULL) 3103 if (afile[i] != NULL)
2861 spell_free_aff(afile[i - 1]); 3104 spell_free_aff(afile[i]);
2862 } 3105 }
2863 3106 }
2864 theend: 3107
2865 FreeWild(fcount, fnames); 3108
2866 } 3109 /*
2867 3110 * ":spellgood {word}"
2868 #endif /* FEAT_MBYTE */ 3111 * ":spellwrong {word}"
3112 */
3113 void
3114 ex_spell(eap)
3115 exarg_T *eap;
3116 {
3117 spell_add_word(eap->arg, STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong);
3118 }
3119
3120 /*
3121 * Add "word[len]" to 'spellfile' as a good or bad word.
3122 */
3123 void
3124 spell_add_word(word, len, bad)
3125 char_u *word;
3126 int len;
3127 int bad;
3128 {
3129 FILE *fd;
3130 buf_T *buf;
3131
3132 if (*curbuf->b_p_spf == NUL)
3133 init_spellfile();
3134 if (*curbuf->b_p_spf == NUL)
3135 EMSG(_("E999: 'spellfile' is not set"));
3136 else
3137 {
3138 /* Check that the user isn't editing the .add file somewhere. */
3139 buf = buflist_findname_exp(curbuf->b_p_spf);
3140 if (buf != NULL && buf->b_ml.ml_mfp == NULL)
3141 buf = NULL;
3142 if (buf != NULL && bufIsChanged(buf))
3143 EMSG(_(e_bufloaded));
3144 else
3145 {
3146 fd = mch_fopen((char *)curbuf->b_p_spf, "a");
3147 if (fd == NULL)
3148 EMSG2(_(e_notopen), curbuf->b_p_spf);
3149 else
3150 {
3151 if (bad)
3152 fprintf(fd, "/!%.*s\n", len, word);
3153 else
3154 fprintf(fd, "%.*s\n", len, word);
3155 fclose(fd);
3156
3157 /* Update the .add.spl file. */
3158 mkspell(1, &curbuf->b_p_spf, FALSE, TRUE, FALSE);
3159
3160 /* If the .add file is edited somewhere, reload it. */
3161 if (buf != NULL)
3162 buf_reload(buf);
3163 }
3164 }
3165 }
3166 }
3167
3168 /*
3169 * Initialize 'spellfile' for the current buffer.
3170 */
3171 static void
3172 init_spellfile()
3173 {
3174 char_u buf[MAXPATHL];
3175 int l;
3176 slang_T *sl;
3177 char_u *rtp;
3178
3179 if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0)
3180 {
3181 /* Loop over all entries in 'runtimepath'. */
3182 rtp = p_rtp;
3183 while (*rtp != NUL)
3184 {
3185 /* Copy the path from 'runtimepath' to buf[]. */
3186 copy_option_part(&rtp, buf, MAXPATHL, ",");
3187 if (filewritable(buf) == 2)
3188 {
3189 sl = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang;
3190 l = STRLEN(buf);
3191 vim_snprintf((char *)buf + l, MAXPATHL - l,
3192 "/spell/%.2s.%s.add",
3193 sl->sl_name,
3194 strstr((char *)gettail(sl->sl_fname), ".ascii.") != NULL
3195 ? (char_u *)"ascii" : spell_enc());
3196 set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
3197 break;
3198 }
3199 }
3200 }
3201 }
2869 3202
2870 3203
2871 /* 3204 /*
2872 * Init the chartab used for spelling for ASCII. 3205 * Init the chartab used for spelling for ASCII.
2873 * EBCDIC is not supported! 3206 * EBCDIC is not supported!
2935 } 3268 }
2936 } 3269 }
2937 } 3270 }
2938 } 3271 }
2939 3272
2940 #if defined(FEAT_MBYTE) || defined(PROTO)
2941 static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP"); 3273 static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP");
2942 static char *e_affrange = N_("E762: Character in FOL, LOW or UPP is out of range"); 3274 static char *e_affrange = N_("E762: Character in FOL, LOW or UPP is out of range");
2943 3275
2944 /* 3276 /*
2945 * Set the spell character tables from strings in the affix file. 3277 * Set the spell character tables from strings in the affix file.
3014 return FAIL; 3346 return FAIL;
3015 } 3347 }
3016 3348
3017 return set_spell_finish(&new_st); 3349 return set_spell_finish(&new_st);
3018 } 3350 }
3019 #endif
3020 3351
3021 /* 3352 /*
3022 * Set the spell character tables from strings in the .spl file. 3353 * Set the spell character tables from strings in the .spl file.
3023 */ 3354 */
3024 static int 3355 static int
3080 } 3411 }
3081 3412
3082 return OK; 3413 return OK;
3083 } 3414 }
3084 3415
3085 #if defined(FEAT_MBYTE) || defined(PROTO)
3086 /* 3416 /*
3087 * Write the current tables into the .spl file. 3417 * Write the current tables into the .spl file.
3088 * This makes sure the same characters are recognized as word characters when 3418 * This makes sure the same characters are recognized as word characters when
3089 * generating an when using a spell file. 3419 * generating an when using a spell file.
3090 */ 3420 */
3105 flags |= SPELL_ISWORD; 3435 flags |= SPELL_ISWORD;
3106 if (spelltab.st_isu[i]) 3436 if (spelltab.st_isu[i])
3107 flags |= SPELL_ISUPPER; 3437 flags |= SPELL_ISUPPER;
3108 fputc(flags, fd); /* <charflags> */ 3438 fputc(flags, fd); /* <charflags> */
3109 3439
3110 len += mb_char2bytes(spelltab.st_fold[i], charbuf + len); 3440 #ifdef FEAT_MBYTE
3441 if (has_mbyte)
3442 len += mb_char2bytes(spelltab.st_fold[i], charbuf + len);
3443 else
3444 #endif
3445 charbuf[len++] = spelltab.st_fold[i];
3111 } 3446 }
3112 3447
3113 put_bytes(fd, (long_u)len, 2); /* <fcharlen> */ 3448 put_bytes(fd, (long_u)len, 2); /* <fcharlen> */
3114 fwrite(charbuf, (size_t)len, (size_t)1, fd); /* <fchars> */ 3449 fwrite(charbuf, (size_t)len, (size_t)1, fd); /* <fchars> */
3115 } 3450 }
3116 #endif
3117 3451
3118 /* 3452 /*
3119 * Return TRUE if "c" is an upper-case character for spelling. 3453 * Return TRUE if "c" is an upper-case character for spelling.
3120 */ 3454 */
3121 static int 3455 static int