1
0
forked from aniani/vim

updated for version 7.0099

This commit is contained in:
Bram Moolenaar
2005-07-01 22:33:52 +00:00
parent 505e82870e
commit 7887d88a9f
4 changed files with 471 additions and 370 deletions

View File

@@ -1,7 +1,7 @@
" These commands create the option window. " These commands create the option window.
" "
" Maintainer: Bram Moolenaar <Bram@vim.org> " Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2005 Mar 07 " Last Change: 2005 Jul 01
" If there already is an option window, jump to that one. " If there already is an option window, jump to that one.
if bufwinnr("option-window") > 0 if bufwinnr("option-window") > 0
@@ -368,7 +368,7 @@ if has("linebreak")
endif endif
call <SID>Header("syntax and highlighting") call <SID>Header("syntax, highlighting and spelling")
call append("$", "background\t\"dark\" or \"light\"; the background color brightness") call append("$", "background\t\"dark\" or \"light\"; the background color brightness")
call <SID>OptionG("bg", &bg) call <SID>OptionG("bg", &bg)
if has("autocmd") if has("autocmd")
@@ -385,6 +385,19 @@ call append("$", "highlight\twhich highlighting to use for various occasions")
call <SID>OptionG("hl", &hl) call <SID>OptionG("hl", &hl)
call append("$", "hlsearch\thighlight all matches for the last used search pattern") call append("$", "hlsearch\thighlight all matches for the last used search pattern")
call <SID>BinOptionG("hls", &hls) call <SID>BinOptionG("hls", &hls)
if has("syntax")
call append("$", "spell\thighlight spelling mistakes")
call append("$", "\t(local to window)")
call <SID>BinOptionL("spell")
call append("$", "spelllang\tlist of accepted languages")
call append("$", "\t(local to buffer)")
call <SID>OptionL("spl")
call append("$", "spellfile\tfile that \"zg\" adds good words to")
call append("$", "\t(local to buffer)")
call <SID>OptionL("spf")
call append("$", "spellsuggest\tmethods used to suggest corrections")
call <SID>OptionG("sps", &sps)
endif
call <SID>Header("multiple windows") call <SID>Header("multiple windows")
@@ -614,6 +627,8 @@ call append("$", "report\tthreshold for reporting number of changed lines")
call append("$", " \tset report=" . &report) call append("$", " \tset report=" . &report)
call append("$", "verbose\tthe higher the more messages are given") call append("$", "verbose\tthe higher the more messages are given")
call append("$", " \tset vbs=" . &vbs) call append("$", " \tset vbs=" . &vbs)
call append("$", "verbosefile\tfile to write messages in")
call <SID>OptionG("vfile", &vfile)
call append("$", "more\tpause listings when the screen is full") call append("$", "more\tpause listings when the screen is full")
call <SID>BinOptionG("more", &more) call <SID>BinOptionG("more", &more)
if has("dialog_con") || has("dialog_gui") if has("dialog_con") || has("dialog_gui")

View File

@@ -3,74 +3,101 @@
# It builds on Windows 95 and all four NT platforms: i386, Alpha, MIPS, and # It builds on Windows 95 and all four NT platforms: i386, Alpha, MIPS, and
# PowerPC. The NT/i386 binary and the Windows 95 binary are identical. # PowerPC. The NT/i386 binary and the Windows 95 binary are identical.
# #
# To build using Borland C++, use Make_bc3.mak or Make_bc5.mak.
#
# This makefile can build the console, GUI, OLE-enable, Perl-enabled and # This makefile can build the console, GUI, OLE-enable, Perl-enabled and
# Python-enabled versions of vim for Win32 platforms. # Python-enabled versions of vim for Win32 platforms.
# #
# When compiling different versions, do "nmake clean" first!
#
# The basic command line to build vim is: # The basic command line to build vim is:
#
# nmake -f Make_mvc.mak # nmake -f Make_mvc.mak
#
# This will build the console version of vim with no additional interfaces. # This will build the console version of vim with no additional interfaces.
# To add interfaces, define any of the following: # To add features, define any of the following:
#
# !!!! After changing features do "nmake clean" first !!!!
#
# Feature Set: FEATURES=[TINY, SMALL, NORMAL, BIG, HUGE] (default is BIG)
#
# GUI interface: GUI=yes (default is no) # GUI interface: GUI=yes (default is no)
#
# OLE interface: OLE=yes (usually with GUI=yes) # OLE interface: OLE=yes (usually with GUI=yes)
#
# Multibyte support: MBYTE=yes # Multibyte support: MBYTE=yes
#
# IME support: IME=yes (requires GUI=yes) # IME support: IME=yes (requires GUI=yes)
# DYNAMIC_IME=[yes or no] (to load the imm32.dll dynamically, default # DYNAMIC_IME=[yes or no] (to load the imm32.dll dynamically, default
# is yes) # is yes)
# Global IME support: GIME=yes (requires GUI=yes) # Global IME support: GIME=yes (requires GUI=yes)
#
# MzScheme interface: # MzScheme interface:
# MZSCHEME=[Path to MzScheme directory] # MZSCHEME=[Path to MzScheme directory]
# DYNAMIC_MZSCHEME=yes (to load the MzScheme DLLs dynamically) # DYNAMIC_MZSCHEME=yes (to load the MzScheme DLLs dynamically)
# MZSCHEME_VER=[version, 205_000, ...] # MZSCHEME_VER=[version, 205_000, ...]
#
# Perl interface: # Perl interface:
# PERL=[Path to Perl directory] # PERL=[Path to Perl directory]
# DYNAMIC_PERL=yes (to load the Perl DLL dynamically) # DYNAMIC_PERL=yes (to load the Perl DLL dynamically)
# PERL_VER=[Perl version, in the form 55 (5.005), 56 (5.6.x), etc] (default is 56) # PERL_VER=[Perl version, in the form 55 (5.005), 56 (5.6.x), etc]
# (default is 56)
#
# Python interface: # Python interface:
# PYTHON=[Path to Python directory] # PYTHON=[Path to Python directory]
# DYNAMIC_PYTHON=yes (to load the Python DLL dynamically) # DYNAMIC_PYTHON=yes (to load the Python DLL dynamically)
# PYTHON_VER=[Python version, eg 15, 20] (default is 22) # PYTHON_VER=[Python version, eg 15, 20] (default is 22)
#
# Ruby interface: # Ruby interface:
# RUBY=[Path to Ruby directory] # RUBY=[Path to Ruby directory]
# DYNAMIC_RUBY=yes (to load the Ruby DLL dynamically) # DYNAMIC_RUBY=yes (to load the Ruby DLL dynamically)
# RUBY_VER=[Ruby version, eg 16, 17] (default is 18) # RUBY_VER=[Ruby version, eg 16, 17] (default is 18)
# RUBY_VER_LONG=[Ruby version, eg 1.6, 1.7] (default is 1.8) # RUBY_VER_LONG=[Ruby version, eg 1.6, 1.7] (default is 1.8)
# You must set RUBY_VER_LONG when change RUBY_VER. # You must set RUBY_VER_LONG when change RUBY_VER.
#
# Tcl interface: # Tcl interface:
# TCL=[Path to Tcl directory] # TCL=[Path to Tcl directory]
# DYNAMIC_TCL=yes (to load the Tcl DLL dynamically) # DYNAMIC_TCL=yes (to load the Tcl DLL dynamically)
# TCL_VER=[Tcl version, e.g. 80, 83] (default is 83) # TCL_VER=[Tcl version, e.g. 80, 83] (default is 83)
# TCL_VER_LONG=[Tcl version, eg 8.3] (default is 8.3) # TCL_VER_LONG=[Tcl version, eg 8.3] (default is 8.3)
# You must set TCL_VER_LONG when you set TCL_VER. # You must set TCL_VER_LONG when you set TCL_VER.
#
# SNiFF+ interface: SNIFF=yes
#
# Cscope support: CSCOPE=yes
#
# Iconv library support (always dynamically loaded):
# ICONV=[yes or no] (default is yes)
#
# Intl library support (always dynamically loaded):
# GETTEXT=[yes or no] (default is yes)
# See http://sourceforge.net/projects/gettext/
#
# PostScript printing: POSTSCRIPT=yes (default is no)
#
# Netbeans Support: NETBEANS=[yes or no] (default is yes if GUI is yes)
#
# XPM Image Support: XPM=[path to XPM directory]
#
# Optimization: OPTIMIZE=[SPACE, SPEED, MAXSPEED] (default is MAXSPEED)
#
# Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
# i386)
#
# Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
#
# Debug version: DEBUG=yes # Debug version: DEBUG=yes
# Mapfile: MAP=[no, yes or lines] (default is yes) # Mapfile: MAP=[no, yes or lines] (default is yes)
# no: Don't write a mapfile. # no: Don't write a mapfile.
# yes: Write a normal mapfile. # yes: Write a normal mapfile.
# lines: Write a mapfile with line numbers (only for VC6 and later) # lines: Write a mapfile with line numbers (only for VC6 and later)
# SNiFF+ interface: SNIFF=yes #
# Cscope support: CSCOPE=yes # Netbeans Debugging Support: NBDEBUG=[yes or no] (should be no, yes
# Iconv library support (always dynamically loaded): # doesn't work)
# ICONV=[yes or no] (default is yes)
# Intl library support (always dynamically loaded):
# GETTEXT=[yes or no] (default is yes)
# See http://sourceforge.net/projects/gettext/
# PostScript printing: POSTSCRIPT=yes (default is no)
# Feature Set: FEATURES=[TINY, SMALL, NORMAL, BIG, HUGE] (default is BIG)
# Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
# Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is i386)
# Optimization: OPTIMIZE=[SPACE, SPEED, MAXSPEED] (default is MAXSPEED)
# Netbeans Support: NETBEANS=[yes or no] (default is yes if GUI is yes)
# Netbeans Debugging Support: NBDEBUG=[yes or no] (default is no)
# XPM Image Support: XPM=[path to XPM directory]
# #
# You can combine any of these interfaces # You can combine any of these interfaces
# #
# Example: To build the non-debug, GUI version with Perl interface: # Example: To build the non-debug, GUI version with Perl interface:
# nmake -f Make_mvc.mak GUI=yes PERL=C:\Perl # nmake -f Make_mvc.mak GUI=yes PERL=C:\Perl
# #
# To build using Borland C++, use Make_bc3.mak or Make_bc5.mak.
#
# DEBUG with Make_mvc.mak and Make_dvc.mak: # DEBUG with Make_mvc.mak and Make_dvc.mak:
# This makefile gives a fineness of control which is not supported in # This makefile gives a fineness of control which is not supported in
# Visual C++ configuration files. Therefore, debugging requires a bit of # Visual C++ configuration files. Therefore, debugging requires a bit of

View File

@@ -4665,6 +4665,8 @@ dozet:
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
case 'g': /* "zg": add good word to word list */ case 'g': /* "zg": add good word to word list */
case 'w': /* "zw": add wrong word to word list */ case 'w': /* "zw": add wrong word to word list */
case 'G': /* "zG": add good word to temp word list */
case 'W': /* "zW": add wrong word to temp word list */
{ {
char_u *ptr = NULL; char_u *ptr = NULL;
int len; int len;
@@ -4679,7 +4681,8 @@ dozet:
if (ptr == NULL && (len = find_ident_under_cursor(&ptr, if (ptr == NULL && (len = find_ident_under_cursor(&ptr,
FIND_IDENT)) == 0) FIND_IDENT)) == 0)
return; return;
spell_add_word(ptr, len, nchar == 'w'); spell_add_word(ptr, len, nchar == 'w' || nchar == 'W',
nchar == 'G' || nchar == 'W');
} }
break; break;

View File

@@ -377,6 +377,9 @@ typedef struct langp_S
#define VIMSPELLMAGIC "VIMspell08" /* string at start of Vim spell file */ #define VIMSPELLMAGIC "VIMspell08" /* string at start of Vim spell file */
#define VIMSPELLMAGICL 10 #define VIMSPELLMAGICL 10
/* file used for "zG" and "zW" */
static char_u *temp_wordlist = NULL;
/* /*
* Information used when looking for suggestions. * Information used when looking for suggestions.
*/ */
@@ -574,10 +577,6 @@ typedef struct trystate_S
#define FIND_KEEPWORD 1 /* find keep-case word */ #define FIND_KEEPWORD 1 /* find keep-case word */
#define FIND_PREFIX 2 /* find word after prefix */ #define FIND_PREFIX 2 /* find word after prefix */
/* values for read_cnt_string() */
#define ERR_NOMEM -1
#define ERR_TRUNC -2
static slang_T *slang_alloc __ARGS((char_u *lang)); static slang_T *slang_alloc __ARGS((char_u *lang));
static void slang_free __ARGS((slang_T *lp)); static void slang_free __ARGS((slang_T *lp));
static void slang_clear __ARGS((slang_T *lp)); static void slang_clear __ARGS((slang_T *lp));
@@ -592,6 +591,8 @@ static char_u *spell_enc __ARGS((void));
static void spell_load_cb __ARGS((char_u *fname, void *cookie)); static void spell_load_cb __ARGS((char_u *fname, void *cookie));
static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent)); static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent));
static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *errp)); static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *errp));
static int set_sofo __ARGS((slang_T *lp, char_u *from, char_u *to));
static void set_sal_first __ARGS((slang_T *lp));
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
static int *mb_str2wide __ARGS((char_u *s)); static int *mb_str2wide __ARGS((char_u *s));
#endif #endif
@@ -601,7 +602,7 @@ static void use_midword __ARGS((slang_T *lp, buf_T *buf));
static int find_region __ARGS((char_u *rp, char_u *region)); static int find_region __ARGS((char_u *rp, char_u *region));
static int captype __ARGS((char_u *word, char_u *end)); static int captype __ARGS((char_u *word, char_u *end));
static void spell_reload_one __ARGS((char_u *fname, int added_word)); static void spell_reload_one __ARGS((char_u *fname, int added_word));
static int set_spell_charflags __ARGS((char_u *flags, int cnt, char_u *upp)); static int set_spell_charflags __ARGS((char_u *flags, char_u *upp));
static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp)); static int set_spell_chartab __ARGS((char_u *fol, char_u *low, char_u *upp));
static void write_spell_chartab __ARGS((FILE *fd)); static void write_spell_chartab __ARGS((FILE *fd));
static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen)); static int spell_casefold __ARGS((char_u *p, int len, char_u *buf, int buflen));
@@ -683,6 +684,7 @@ static linenr_T apply_prefixes __ARGS((slang_T *slang, char_u *word, int round,
static char *e_format = N_("E759: Format error in spell file"); static char *e_format = N_("E759: Format error in spell file");
static char *e_spell_trunc = N_("E758: Truncated spell file");
/* /*
* Main spell-checking function. * Main spell-checking function.
@@ -1690,9 +1692,7 @@ spell_load_file(fname, lang, old_lp, silent)
garray_T *gap; garray_T *gap;
fromto_T *ftp; fromto_T *ftp;
salitem_T *smp; salitem_T *smp;
int rr;
short *first; short *first;
salfirst_T *sfirst;
idx_T idx; idx_T idx;
int c = 0; int c = 0;
@@ -1756,7 +1756,7 @@ spell_load_file(fname, lang, old_lp, silent)
if (cnt < 0) if (cnt < 0)
{ {
truncerr: truncerr:
EMSG(_("E758: Truncated spell file")); EMSG(_(e_spell_trunc));
goto endFAIL; goto endFAIL;
} }
if (cnt > 8) if (cnt > 8)
@@ -1772,48 +1772,33 @@ formerr:
} }
lp->sl_regions[cnt * 2] = NUL; lp->sl_regions[cnt * 2] = NUL;
cnt = getc(fd); /* <charflagslen> */ /* <charflagslen> <charflags> */
if (cnt > 0) p = read_cnt_string(fd, 1, &cnt);
{ if (cnt == FAIL)
p = alloc((unsigned)cnt);
if (p == NULL)
goto endFAIL; goto endFAIL;
for (i = 0; i < cnt; ++i)
p[i] = getc(fd); /* <charflags> */
/* <fcharslen> <fchars> */ /* <fcharslen> <fchars> */
fol = read_cnt_string(fd, 2, &ccnt); fol = read_cnt_string(fd, 2, &cnt);
if (ccnt != 0) if (cnt == FAIL)
{ {
vim_free(p); vim_free(p);
if (ccnt == ERR_NOMEM)
goto endFAIL; goto endFAIL;
if (ccnt == ERR_TRUNC)
goto formerr;
} }
/* Set the word-char flags and fill SPELL_ISUPPER() table. */ /* Set the word-char flags and fill SPELL_ISUPPER() table. */
i = set_spell_charflags(p, cnt, fol); if (p != NULL && fol != NULL)
i = set_spell_charflags(p, fol);
vim_free(p); vim_free(p);
vim_free(fol); vim_free(fol);
#if 0 /* tolerate the differences */
if (i == FAIL)
goto formerr;
#endif
}
else
{
/* When <charflagslen> is zero then <fcharlen> must also be zero. */ /* When <charflagslen> is zero then <fcharlen> must also be zero. */
cnt = (getc(fd) << 8) + getc(fd); if ((p == NULL) != (fol == NULL))
if (cnt != 0)
goto formerr; goto formerr;
}
/* <midwordlen> <midword> */ /* <midwordlen> <midword> */
lp->sl_midword = read_cnt_string(fd, 2, &cnt); lp->sl_midword = read_cnt_string(fd, 2, &cnt);
if (cnt == ERR_TRUNC) if (cnt == FAIL)
goto truncerr;
if (cnt == ERR_NOMEM)
goto endFAIL; goto endFAIL;
/* <prefcondcnt> <prefcond> ... */ /* <prefcondcnt> <prefcond> ... */
@@ -1863,29 +1848,15 @@ formerr:
for (; gap->ga_len < cnt; ++gap->ga_len) for (; gap->ga_len < cnt; ++gap->ga_len)
{ {
ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; ftp = &((fromto_T *)gap->ga_data)[gap->ga_len];
for (rr = 1; rr <= 2; ++rr) ftp->ft_from = read_cnt_string(fd, 1, &i);
if (i == FAIL)
goto endFAIL;
ftp->ft_to = read_cnt_string(fd, 1, &i);
if (i == FAIL)
{ {
ccnt = getc(fd);
if (ccnt < 0)
{
if (rr == 2)
vim_free(ftp->ft_from);
goto formerr;
}
if ((p = alloc(ccnt + 1)) == NULL)
{
if (rr == 2)
vim_free(ftp->ft_from); vim_free(ftp->ft_from);
goto endFAIL; goto endFAIL;
} }
for (i = 0; i < ccnt; ++i)
p[i] = getc(fd); /* <repfrom> or <repto> */
p[i] = NUL;
if (rr == 1)
ftp->ft_from = p;
else
ftp->ft_to = p;
}
} }
/* Fill the first-index table. */ /* Fill the first-index table. */
@@ -1921,118 +1892,27 @@ formerr:
if (cnt != 1) if (cnt != 1)
goto formerr; goto formerr;
cnt = (getc(fd) << 8) + getc(fd); /* <salfromlen> */ /* <salfromlen> <salfrom> */
if (cnt < 0) bp = read_cnt_string(fd, 2, &cnt);
goto formerr; if (cnt == FAIL)
if ((bp = alloc(cnt + 1)) == NULL)
goto endFAIL; goto endFAIL;
for (i = 0; i < cnt; ++i)
bp[i] = getc(fd); /* <salfrom> */
bp[i] = NUL;
ccnt = (getc(fd) << 8) + getc(fd); /* <saltolen> */ /* <saltolen> <salto> */
if (ccnt < 0) fol = read_cnt_string(fd, 2, &cnt);
{ if (cnt == FAIL)
vim_free(bp);
goto formerr;
}
if ((fol = alloc(ccnt + 1)) == NULL)
{ {
vim_free(bp); vim_free(bp);
goto endFAIL; goto endFAIL;
} }
for (i = 0; i < ccnt; ++i)
fol[i] = getc(fd); /* <salto> */
fol[i] = NUL;
#ifdef FEAT_MBYTE /* Store the info in lp->sl_sal and/or lp->sl_sal_first. */
if (has_mbyte) i = set_sofo(lp, bp, fol);
{
char_u *s;
/* Use "sl_sal" as an array with 256 pointers to a list of wide
* characters. The index is the low byte of the character.
* The list contains from-to pairs with a terminating NUL.
* sl_sal_first[] is used for latin1 "from" characters. */
gap = &lp->sl_sal;
ga_init2(gap, sizeof(int *), 1);
if (ga_grow(gap, 256) == FAIL)
{
sofoFAIL:
vim_free(bp);
vim_free(fol);
goto endFAIL;
}
vim_memset(gap->ga_data, 0, sizeof(int *) * 256);
gap->ga_len = 256;
/* First count the number of items for each list. Temporarily use
* sl_sal_first[] for this. */
for (p = bp, s = fol; *p != NUL && *s != NUL; )
{
c = mb_ptr2char_adv(&p);
mb_ptr_adv(s);
if (c >= 256)
++lp->sl_sal_first[c & 0xff];
}
if (*p != NUL || *s != NUL) /* lengths differ */
goto sofoerr;
/* Allocate the lists. */
for (i = 0; i < 256; ++i)
if (lp->sl_sal_first[i] > 0)
{
p = alloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1));
if (p == NULL)
goto sofoFAIL;
((int **)gap->ga_data)[i] = (int *)p;
*(int *)p = 0;
}
/* Put the characters in sl_sal_first[] or a sl_sal list. */
vim_memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
for (p = bp, s = fol; *p != NUL && *s != NUL; )
{
c = mb_ptr2char_adv(&p);
i = mb_ptr2char_adv(&s);
if (c >= 256)
{
int *inp;
/* Append the from-to chars at the end of the list with
* the low byte. */
inp = ((int **)gap->ga_data)[c & 0xff];
while (*inp != 0)
++inp;
*inp++ = c; /* from char */
*inp++ = i; /* to char */
*inp++ = NUL; /* NUL at the end */
}
else
/* mapping byte to char is done in sl_sal_first[] */
lp->sl_sal_first[c] = i;
}
}
else
#endif
{
/* mapping bytes to bytes is done in sl_sal_first[] */
if (cnt != ccnt)
{
#ifdef FEAT_MBYTE
sofoerr:
#endif
vim_free(bp); vim_free(bp);
vim_free(fol); vim_free(fol);
if (i == FAIL)
goto formerr; goto formerr;
} }
for (i = 0; i < cnt; ++i)
lp->sl_sal_first[bp[i]] = fol[i];
lp->sl_sal.ga_len = 1; /* indicates we have soundfolding */
}
vim_free(bp);
vim_free(fol);
}
else else
{ {
/* /*
@@ -2091,22 +1971,13 @@ sofoerr:
*p++ = getc(fd); /* <salfrom> */ *p++ = getc(fd); /* <salfrom> */
*p++ = NUL; *p++ = NUL;
ccnt = getc(fd); /* <saltolen> */ /* <saltolen> <salto> */
if (ccnt < 0) smp->sm_to = read_cnt_string(fd, 1, &ccnt);
if (ccnt == FAIL)
{ {
vim_free(smp->sm_lead); vim_free(smp->sm_lead);
goto formerr; goto formerr;
} }
if ((p = alloc(ccnt + 1)) == NULL)
{
vim_free(smp->sm_lead);
goto endFAIL;
}
smp->sm_to = p;
for (i = 0; i < ccnt; ++i)
*p++ = getc(fd); /* <salto> */
*p++ = NUL;
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
@@ -2135,64 +2006,13 @@ sofoerr:
} }
/* Fill the first-index table. */ /* Fill the first-index table. */
sfirst = lp->sl_sal_first; set_sal_first(lp);
for (i = 0; i < 256; ++i)
sfirst[i] = -1;
smp = (salitem_T *)gap->ga_data;
for (i = 0; i < gap->ga_len; ++i)
{
#ifdef FEAT_MBYTE
if (has_mbyte)
/* Use the lowest byte of the first character. For latin1 it's
* the character, for other encodings it should differ for most
* characters. */
c = *smp[i].sm_lead_w & 0xff;
else
#endif
c = *smp[i].sm_lead;
if (sfirst[c] == -1)
{
sfirst[c] = i;
#ifdef FEAT_MBYTE
if (has_mbyte)
{
/* Make sure all entries with this byte are following each
* other. Move the ones that are in the wrong position. Do
* keep the same ordering! */
while (i + 1 < gap->ga_len
&& (*smp[i + 1].sm_lead_w & 0xff) == c)
/* Skip over entry with same index byte. */
++i;
for (n = 1; i + n < gap->ga_len; ++n)
if ((*smp[i + n].sm_lead_w & 0xff) == c)
{
salitem_T tsal;
/* Move entry with same index byte after the entries
* we already found. */
++i;
--n;
tsal = smp[i + n];
mch_memmove(smp + i + 1, smp + i,
sizeof(salitem_T) * n);
smp[i] = tsal;
}
}
#endif
}
}
} }
cnt = (getc(fd) << 8) + getc(fd); /* <maplen> */ /* <maplen> <mapstr> */
if (cnt < 0) p = read_cnt_string(fd, 2, &cnt);
goto formerr; if (cnt == FAIL)
p = alloc(cnt + 1);
if (p == NULL)
goto endFAIL; goto endFAIL;
for (i = 0; i < cnt; ++i)
p[i] = getc(fd); /* <mapstr> */
p[i] = NUL;
set_map_str(lp, p); set_map_str(lp, p);
vim_free(p); vim_free(p);
@@ -2270,10 +2090,9 @@ endOK:
/* /*
* Read a length field from "fd" in "cnt_bytes" bytes. * Read a length field from "fd" in "cnt_bytes" bytes.
* Allocate memory and read the string into it. * Allocate memory, read the string into it and add a NUL at the end.
* Returns NULL when the count is zero. * Returns NULL when the count is zero.
* Sets "errp" to ERR_TRUNC when reading failed, ERR_NOMEM when out of * Sets "*errp" to FAIL when there is an error, OK otherwise.
* memory, zero when OK.
*/ */
static char_u * static char_u *
read_cnt_string(fd, cnt_bytes, errp) read_cnt_string(fd, cnt_bytes, errp)
@@ -2290,7 +2109,8 @@ read_cnt_string(fd, cnt_bytes, errp)
cnt = (cnt << 8) + getc(fd); cnt = (cnt << 8) + getc(fd);
if (cnt < 0) if (cnt < 0)
{ {
*errp = ERR_TRUNC; EMSG(_(e_spell_trunc));
*errp = FAIL;
return NULL; return NULL;
} }
@@ -2298,10 +2118,10 @@ read_cnt_string(fd, cnt_bytes, errp)
str = alloc((unsigned)cnt + 1); str = alloc((unsigned)cnt + 1);
if (str == NULL) if (str == NULL)
{ {
*errp = ERR_NOMEM; *errp = FAIL;
return NULL; return NULL;
} }
*errp = 0; *errp = OK;
/* Read the string. Doesn't check for truncated file. */ /* Read the string. Doesn't check for truncated file. */
for (i = 0; i < cnt; ++i) for (i = 0; i < cnt; ++i)
@@ -2311,6 +2131,162 @@ read_cnt_string(fd, cnt_bytes, errp)
return str; return str;
} }
/*
* Set the SOFOFROM and SOFOTO items in language "lp".
* Returns FAIL when there is something wrong.
*/
static int
set_sofo(lp, from, to)
slang_T *lp;
char_u *from;
char_u *to;
{
int i;
#ifdef FEAT_MBYTE
garray_T *gap;
char_u *s;
char_u *p;
int c;
int *inp;
if (has_mbyte)
{
/* Use "sl_sal" as an array with 256 pointers to a list of wide
* characters. The index is the low byte of the character.
* The list contains from-to pairs with a terminating NUL.
* sl_sal_first[] is used for latin1 "from" characters. */
gap = &lp->sl_sal;
ga_init2(gap, sizeof(int *), 1);
if (ga_grow(gap, 256) == FAIL)
return FAIL;
vim_memset(gap->ga_data, 0, sizeof(int *) * 256);
gap->ga_len = 256;
/* First count the number of items for each list. Temporarily use
* sl_sal_first[] for this. */
for (p = from, s = to; *p != NUL && *s != NUL; )
{
c = mb_ptr2char_adv(&p);
mb_ptr_adv(s);
if (c >= 256)
++lp->sl_sal_first[c & 0xff];
}
if (*p != NUL || *s != NUL) /* lengths differ */
return FAIL;
/* Allocate the lists. */
for (i = 0; i < 256; ++i)
if (lp->sl_sal_first[i] > 0)
{
p = alloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1));
if (p == NULL)
return FAIL;
((int **)gap->ga_data)[i] = (int *)p;
*(int *)p = 0;
}
/* Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal
* list. */
vim_memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
for (p = from, s = to; *p != NUL && *s != NUL; )
{
c = mb_ptr2char_adv(&p);
i = mb_ptr2char_adv(&s);
if (c >= 256)
{
/* Append the from-to chars at the end of the list with
* the low byte. */
inp = ((int **)gap->ga_data)[c & 0xff];
while (*inp != 0)
++inp;
*inp++ = c; /* from char */
*inp++ = i; /* to char */
*inp++ = NUL; /* NUL at the end */
}
else
/* mapping byte to char is done in sl_sal_first[] */
lp->sl_sal_first[c] = i;
}
}
else
#endif
{
/* mapping bytes to bytes is done in sl_sal_first[] */
if (STRLEN(from) != STRLEN(to))
return FAIL;
for (i = 0; to[i] != NUL; ++i)
lp->sl_sal_first[from[i]] = to[i];
lp->sl_sal.ga_len = 1; /* indicates we have soundfolding */
}
return OK;
}
/*
* Fill the first-index table for "lp".
*/
static void
set_sal_first(lp)
slang_T *lp;
{
salfirst_T *sfirst;
int i;
salitem_T *smp;
int c;
garray_T *gap = &lp->sl_sal;
sfirst = lp->sl_sal_first;
for (i = 0; i < 256; ++i)
sfirst[i] = -1;
smp = (salitem_T *)gap->ga_data;
for (i = 0; i < gap->ga_len; ++i)
{
#ifdef FEAT_MBYTE
if (has_mbyte)
/* Use the lowest byte of the first character. For latin1 it's
* the character, for other encodings it should differ for most
* characters. */
c = *smp[i].sm_lead_w & 0xff;
else
#endif
c = *smp[i].sm_lead;
if (sfirst[c] == -1)
{
sfirst[c] = i;
#ifdef FEAT_MBYTE
if (has_mbyte)
{
int n;
/* Make sure all entries with this byte are following each
* other. Move the ones that are in the wrong position. Do
* keep the same ordering! */
while (i + 1 < gap->ga_len
&& (*smp[i + 1].sm_lead_w & 0xff) == c)
/* Skip over entry with same index byte. */
++i;
for (n = 1; i + n < gap->ga_len; ++n)
if ((*smp[i + n].sm_lead_w & 0xff) == c)
{
salitem_T tsal;
/* Move entry with same index byte after the entries
* we already found. */
++i;
--n;
tsal = smp[i + n];
mch_memmove(smp + i + 1, smp + i,
sizeof(salitem_T) * n);
smp[i] = tsal;
}
}
#endif
}
}
}
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
/* /*
@@ -2472,6 +2448,7 @@ did_set_spelllang(buf)
int load_spf; int load_spf;
int len; int len;
char_u *p; char_u *p;
int round;
ga_init2(&ga, sizeof(langp_T), 2); ga_init2(&ga, sizeof(langp_T), 2);
clear_midword(buf); clear_midword(buf);
@@ -2572,12 +2549,26 @@ did_set_spelllang(buf)
} }
} }
/* /* round 1: load 'spellfile', if needed.
* Make sure the 'spellfile' file is loaded. It may be in 'runtimepath', * round 2: load temp_wordlist, if possible. */
* then it's probably loaded above already. Otherwise load it here. for (round = 1; round <= 2; ++round)
*/
if (load_spf)
{ {
if (round == 1)
{
/* Make sure the 'spellfile' file is loaded. It may be in
* 'runtimepath', then it's probably loaded above already.
* Otherwise load it here. */
if (!load_spf)
continue;
}
else
{
if (temp_wordlist == NULL)
continue;
vim_snprintf((char *)spf_name, sizeof(spf_name), "%s.%s.spl",
temp_wordlist, spell_enc());
}
/* Check if it was loaded already. */ /* Check if it was loaded already. */
for (lp = first_lang; lp != NULL; lp = lp->sl_next) for (lp = first_lang; lp != NULL; lp = lp->sl_next)
if (fullpathcmp(spf_name, lp->sl_fname, FALSE) == FPC_SAME) if (fullpathcmp(spf_name, lp->sl_fname, FALSE) == FPC_SAME)
@@ -2585,11 +2576,17 @@ did_set_spelllang(buf)
if (lp == NULL) if (lp == NULL)
{ {
/* Not loaded, try loading it now. The language name includes the /* Not loaded, try loading it now. The language name includes the
* region name, the region is ignored otherwise. */ * region name, the region is ignored otherwise. for
* temp_wordlist use an arbitrary name. */
if (round == 1)
{
vim_strncpy(lang, gettail(buf->b_p_spf), MAXWLEN); vim_strncpy(lang, gettail(buf->b_p_spf), MAXWLEN);
p = vim_strchr(lang, '.'); p = vim_strchr(lang, '.');
if (p != NULL) if (p != NULL)
*p = NUL; /* truncate at ".encoding.add" */ *p = NUL; /* truncate at ".encoding.add" */
}
else
STRCPY(lang, "temp wordlist");
lp = spell_load_file(spf_name, lang, NULL, TRUE); lp = spell_load_file(spf_name, lang, NULL, TRUE);
} }
if (lp != NULL && ga_grow(&ga, 1) == OK) if (lp != NULL && ga_grow(&ga, 1) == OK)
@@ -2678,7 +2675,7 @@ use_midword(lp, buf)
/* /*
* Find the region "region[2]" in "rp" (points to "sl_regions"). * Find the region "region[2]" in "rp" (points to "sl_regions").
* Each region is simply stored as the two characters of it's name. * Each region is simply stored as the two characters of it's name.
* Returns the index if found, REGION_ALL if not found. * Returns the index if found (first is 0), REGION_ALL if not found.
*/ */
static int static int
find_region(rp, region) find_region(rp, region)
@@ -2780,6 +2777,13 @@ spell_free_all()
slang_free(lp); slang_free(lp);
} }
if (temp_wordlist != NULL)
{
mch_remove(temp_wordlist);
vim_free(temp_wordlist);
temp_wordlist = NULL;
}
init_spell_chartab(); init_spell_chartab();
} }
# endif # endif
@@ -3967,6 +3971,7 @@ spell_read_wordfile(fname, spin)
char_u rline[MAXLINELEN]; char_u rline[MAXLINELEN];
char_u *line; char_u *line;
char_u *pc = NULL; char_u *pc = NULL;
char_u *p;
int l; int l;
int retval = OK; int retval = OK;
int did_word = FALSE; int did_word = FALSE;
@@ -4035,13 +4040,9 @@ spell_read_wordfile(fname, spin)
line = rline; line = rline;
} }
flags = 0;
regionmask = spin->si_region;
if (*line == '/') if (*line == '/')
{ {
++line; ++line;
if (STRNCMP(line, "encoding=", 9) == 0) if (STRNCMP(line, "encoding=", 9) == 0)
{ {
if (spin->si_conv.vc_type != CONV_NONE) if (spin->si_conv.vc_type != CONV_NONE)
@@ -4092,50 +4093,49 @@ spell_read_wordfile(fname, spin)
continue; continue;
} }
if (*line == '=') smsg((char_u *)_("/ line ignored in %s line %d: %s"),
fname, lnum, line - 1);
continue;
}
flags = 0;
regionmask = spin->si_region;
/* Check for flags and region after a slash. */
p = vim_strchr(line, '/');
if (p != NULL)
{ {
/* keep-case word */ *p++ = NUL;
while (*p != NUL)
{
if (*p == '=') /* keep-case word */
flags |= WF_KEEPCAP; flags |= WF_KEEPCAP;
++line; else if (*p == '!') /* Bad, bad, wicked word. */
}
if (*line == '!')
{
/* Bad, bad, wicked word. */
flags |= WF_BANNED; flags |= WF_BANNED;
++line; else if (*p == '?') /* Rare word. */
}
else if (*line == '?')
{
/* Rare word. */
flags |= WF_RARE; flags |= WF_RARE;
++line; else if (VIM_ISDIGIT(*p)) /* region number(s) */
}
if (VIM_ISDIGIT(*line))
{ {
/* region number(s) */ if ((flags & WF_REGION) == 0) /* first one */
regionmask = 0; regionmask = 0;
while (VIM_ISDIGIT(*line)) flags |= WF_REGION;
{
l = *line - '0'; l = *p - '0';
if (l > spin->si_region_count) if (l > spin->si_region_count)
{ {
smsg((char_u *)_("Invalid region nr in %s line %d: %s"), smsg((char_u *)_("Invalid region nr in %s line %d: %s"),
fname, lnum, line); fname, lnum, p);
break; break;
} }
regionmask |= 1 << (l - 1); regionmask |= 1 << (l - 1);
++line;
} }
flags |= WF_REGION; else
}
if (flags == 0)
{ {
smsg((char_u *)_("/ line ignored in %s line %d: %s"), smsg((char_u *)_("Unrecognized flags in %s line %d: %s"),
fname, lnum, line); fname, lnum, p);
continue; break;
}
++p;
} }
} }
@@ -5179,23 +5179,38 @@ mkspell(fcount, fnames, ascii, overwrite, added_word)
ex_spell(eap) ex_spell(eap)
exarg_T *eap; exarg_T *eap;
{ {
spell_add_word(eap->arg, STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong); spell_add_word(eap->arg, STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
eap->forceit);
} }
/* /*
* Add "word[len]" to 'spellfile' as a good or bad word. * Add "word[len]" to 'spellfile' as a good or bad word.
*/ */
void void
spell_add_word(word, len, bad) spell_add_word(word, len, bad, temp)
char_u *word; char_u *word;
int len; int len;
int bad; int bad;
int temp; /* "zG" and "zW": use temp word list */
{ {
FILE *fd; FILE *fd;
buf_T *buf; buf_T *buf;
int new_spf = FALSE; int new_spf = FALSE;
struct stat st; struct stat st;
char_u *fname;
if (temp) /* use temp word list */
{
if (temp_wordlist == NULL)
{
temp_wordlist = vim_tempname('s');
if (temp_wordlist == NULL)
return;
}
fname = temp_wordlist;
}
else
{
/* If 'spellfile' isn't set figure out a good default value. */ /* If 'spellfile' isn't set figure out a good default value. */
if (*curbuf->b_p_spf == NUL) if (*curbuf->b_p_spf == NUL)
{ {
@@ -5204,47 +5219,53 @@ spell_add_word(word, len, bad)
} }
if (*curbuf->b_p_spf == NUL) if (*curbuf->b_p_spf == NUL)
EMSG(_("E764: 'spellfile' is not set"));
else
{ {
EMSG(_("E764: 'spellfile' is not set"));
return;
}
/* Check that the user isn't editing the .add file somewhere. */ /* Check that the user isn't editing the .add file somewhere. */
buf = buflist_findname_exp(curbuf->b_p_spf); buf = buflist_findname_exp(curbuf->b_p_spf);
if (buf != NULL && buf->b_ml.ml_mfp == NULL) if (buf != NULL && buf->b_ml.ml_mfp == NULL)
buf = NULL; buf = NULL;
if (buf != NULL && bufIsChanged(buf)) if (buf != NULL && bufIsChanged(buf))
EMSG(_(e_bufloaded));
else
{ {
fd = mch_fopen((char *)curbuf->b_p_spf, "a"); EMSG(_(e_bufloaded));
return;
}
fname = curbuf->b_p_spf;
}
fd = mch_fopen((char *)fname, "a");
if (fd == NULL && new_spf) if (fd == NULL && new_spf)
{ {
/* We just initialized the 'spellfile' option and can't open /* We just initialized the 'spellfile' option and can't open the file.
* the file. We may need to create the "spell" directory * We may need to create the "spell" directory first. We already
* first. We already checked the runtime directory is * checked the runtime directory is writable in init_spellfile(). */
* writable in init_spellfile(). */ STRCPY(NameBuff, fname);
STRCPY(NameBuff, curbuf->b_p_spf);
*gettail_sep(NameBuff) = NUL; *gettail_sep(NameBuff) = NUL;
if (mch_stat((char *)NameBuff, &st) < 0) if (mch_stat((char *)NameBuff, &st) < 0)
{ {
/* The directory doesn't exist. Try creating it and /* The directory doesn't exist. Try creating it and opening the
* opening the file again. */ * file again. */
vim_mkdir(NameBuff, 0755); vim_mkdir(NameBuff, 0755);
fd = mch_fopen((char *)curbuf->b_p_spf, "a"); fd = mch_fopen((char *)fname, "a");
} }
} }
if (fd == NULL) if (fd == NULL)
EMSG2(_(e_notopen), curbuf->b_p_spf); EMSG2(_(e_notopen), fname);
else else
{ {
if (bad) if (bad)
fprintf(fd, "/!%.*s\n", len, word); fprintf(fd, "%.*s/!\n", len, word);
else else
fprintf(fd, "%.*s\n", len, word); fprintf(fd, "%.*s\n", len, word);
fclose(fd); fclose(fd);
/* Update the .add.spl file. */ /* Update the .add.spl file. */
mkspell(1, &curbuf->b_p_spf, FALSE, TRUE, TRUE); mkspell(1, &fname, FALSE, TRUE, TRUE);
/* If the .add file is edited somewhere, reload it. */ /* If the .add file is edited somewhere, reload it. */
if (buf != NULL) if (buf != NULL)
@@ -5252,8 +5273,6 @@ spell_add_word(word, len, bad)
redraw_all_later(NOT_VALID); redraw_all_later(NOT_VALID);
} }
}
}
} }
/* /*
@@ -5475,9 +5494,8 @@ set_spell_chartab(fol, low, upp)
* Set the spell character tables from strings in the .spl file. * Set the spell character tables from strings in the .spl file.
*/ */
static int static int
set_spell_charflags(flags, cnt, upp) set_spell_charflags(flags, upp)
char_u *flags; char_u *flags;
int cnt;
char_u *upp; char_u *upp;
{ {
/* We build the new tables here first, so that we can compare with the /* We build the new tables here first, so that we can compare with the
@@ -5489,7 +5507,7 @@ set_spell_charflags(flags, cnt, upp)
clear_spell_chartab(&new_st); clear_spell_chartab(&new_st);
for (i = 0; i < cnt; ++i) for (i = 0; flags[i] != NUL; ++i)
{ {
new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0;
new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0;
@@ -9362,6 +9380,9 @@ ex_spelldump(eap)
int depth; int depth;
int n; int n;
int flags; int flags;
char_u *region_names = NULL; /* region names being used */
int do_region = TRUE; /* dump region names and numbers */
char_u *p;
if (no_spell_checking()) if (no_spell_checking())
return; return;
@@ -9371,6 +9392,34 @@ ex_spelldump(eap)
if (!bufempty() || !buf_valid(buf)) if (!bufempty() || !buf_valid(buf))
return; return;
/* Find out if we can support regions: All languages must support the same
* regions or none at all. */
for (lp = LANGP_ENTRY(buf->b_langp, 0); lp->lp_slang != NULL; ++lp)
{
p = lp->lp_slang->sl_regions;
if (p[0] != 0)
{
if (region_names == NULL) /* first language with regions */
region_names = p;
else if (STRCMP(region_names, p) != 0)
{
do_region = FALSE; /* region names are different */
break;
}
}
}
if (do_region && region_names != NULL)
{
vim_snprintf((char *)IObuff, IOSIZE, "/regions=%s", region_names);
ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
}
else
do_region = FALSE;
/*
* Loop over all files loaded for the entries in 'spelllang'.
*/
for (lp = LANGP_ENTRY(buf->b_langp, 0); lp->lp_slang != NULL; ++lp) for (lp = LANGP_ENTRY(buf->b_langp, 0); lp->lp_slang != NULL; ++lp)
{ {
slang = lp->lp_slang; slang = lp->lp_slang;
@@ -9420,11 +9469,14 @@ ex_spelldump(eap)
* Only use the word when the region matches. */ * Only use the word when the region matches. */
flags = (int)idxs[n]; flags = (int)idxs[n];
if ((round == 2 || (flags & WF_KEEPCAP) == 0) if ((round == 2 || (flags & WF_KEEPCAP) == 0)
&& ((flags & WF_REGION) == 0 && (do_region
|| (flags & WF_REGION) == 0
|| (((unsigned)flags >> 8) || (((unsigned)flags >> 8)
& lp->lp_region) != 0)) & lp->lp_region) != 0))
{ {
word[depth] = NUL; word[depth] = NUL;
if (!do_region)
flags &= ~WF_REGION;
/* Dump the basic word if there is no prefix or /* Dump the basic word if there is no prefix or
* when it's the first one. */ * when it's the first one. */
@@ -9470,7 +9522,8 @@ dump_word(word, round, flags, lnum)
int keepcap = FALSE; int keepcap = FALSE;
char_u *p; char_u *p;
char_u cword[MAXWLEN]; char_u cword[MAXWLEN];
char_u badword[MAXWLEN + 3]; char_u badword[MAXWLEN + 10];
int i;
if (round == 1 && (flags & WF_CAPMASK) != 0) if (round == 1 && (flags & WF_CAPMASK) != 0)
{ {
@@ -9485,18 +9538,21 @@ dump_word(word, round, flags, lnum)
keepcap = TRUE; keepcap = TRUE;
} }
/* Bad word is preceded by "/!" and some other /* Add flags and regions after a slash. */
* flags. */ if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap)
if ((flags & (WF_BANNED | WF_RARE)) || keepcap)
{ {
STRCPY(badword, "/"); STRCPY(badword, p);
STRCAT(badword, "/");
if (keepcap) if (keepcap)
STRCAT(badword, "="); STRCAT(badword, "=");
if (flags & WF_BANNED) if (flags & WF_BANNED)
STRCAT(badword, "!"); STRCAT(badword, "!");
else if (flags & WF_RARE) else if (flags & WF_RARE)
STRCAT(badword, "?"); STRCAT(badword, "?");
STRCAT(badword, p); if (flags & WF_REGION)
for (i = 0; i < 7; ++i)
if (flags & (0x100 << i))
sprintf((char *)badword + STRLEN(badword), "%d", i + 1);
p = badword; p = badword;
} }