summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-04-15 21:00:38 +0000
committerBram Moolenaar <Bram@vim.org>2005-04-15 21:00:38 +0000
commit402d2fea7025356c7abcb891017a1b7ddf99cbbf (patch)
tree83c5973b6316912331d4a4c070996d7888097e5c /src
parent4499d2ee58db42e4ec59bb2c2dbb5eeca2313e8b (diff)
updated for version 7.0066
Diffstat (limited to 'src')
-rw-r--r--src/Makefile25
-rw-r--r--src/charset.c23
-rw-r--r--src/ex_docmd.c20
-rw-r--r--src/fileio.c5
-rw-r--r--src/gui.c13
-rw-r--r--src/gui_kde_x11.cc12
-rw-r--r--src/gui_w32.c4
-rw-r--r--src/macros.h2
-rw-r--r--src/mbyte.c5
-rw-r--r--src/misc2.c3
-rw-r--r--src/normal.c25
-rw-r--r--src/os_unix.c2
-rw-r--r--src/quickfix.c9
-rw-r--r--src/regexp.c92
-rw-r--r--src/screen.c4
-rw-r--r--src/spell.c4025
-rw-r--r--src/tag.c8
-rw-r--r--src/version.h4
18 files changed, 4040 insertions, 241 deletions
diff --git a/src/Makefile b/src/Makefile
index 366dcddb6c..16d3338ecd 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1292,6 +1292,9 @@ DEST_MAN_TOP = $(DESTDIR)$(MANDIR)
# directory first.
# FreeBSD uses ".../man/xx.ISO8859-1/man1" for latin1, use that one too.
DEST_MAN = $(DEST_MAN_TOP)$(MAN1DIR)
+DEST_MAN_FR = $(DEST_MAN_TOP)/fr$(MAN1DIR)
+DEST_MAN_FR_I = $(DEST_MAN_TOP)/fr.ISO8859-1$(MAN1DIR)
+DEST_MAN_FR_U = $(DEST_MAN_TOP)/fr.UTF-8$(MAN1DIR)
DEST_MAN_IT = $(DEST_MAN_TOP)/it$(MAN1DIR)
DEST_MAN_IT_I = $(DEST_MAN_TOP)/it.ISO8859-1$(MAN1DIR)
DEST_MAN_IT_U = $(DEST_MAN_TOP)/it.UTF-8$(MAN1DIR)
@@ -1823,6 +1826,9 @@ installtools: $(TOOLS) $(DESTDIR)$(exec_prefix) $(DEST_BIN) \
$(STRIP) $(DEST_BIN)/xxd$(EXEEXT)
chmod $(BINMOD) $(DEST_BIN)/xxd$(EXEEXT)
-$(SHELL) ./installman.sh xxd $(DEST_MAN) "" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh xxd $(DEST_MAN_FR) "-fr" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh xxd $(DEST_MAN_FR_I) "-fr" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh xxd $(DEST_MAN_FR_U) "-fr.UTF-8" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh xxd $(DEST_MAN_IT) "-it" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh xxd $(DEST_MAN_IT_I) "-it" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh xxd $(DEST_MAN_IT_U) "-it.UTF-8" $(INSTALLMANARGS)
@@ -1845,12 +1851,21 @@ installtools: $(TOOLS) $(DESTDIR)$(exec_prefix) $(DEST_BIN) \
# install the language specific files, if they were unpacked
install-languages: languages $(DEST_LANG) $(DEST_KMAP)
+ -$(SHELL) ./installman.sh install $(DEST_MAN_FR) "-fr" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh install $(DEST_MAN_FR_I) "-fr" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh install $(DEST_MAN_FR_U) "-fr.UTF-8" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh install $(DEST_MAN_IT) "-it" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh install $(DEST_MAN_IT_I) "-it" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh install $(DEST_MAN_IT_U) "-it.UTF-8" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh install $(DEST_MAN_RU) "-ru" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh install $(DEST_MAN_RU_U) "-ru.UTF-8" $(INSTALLMANARGS)
-$(SHELL) ./installml.sh install "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh install "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR_I) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh install "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR_U) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh install "$(GUI_MAN_TARGETS)" \
$(DEST_MAN_IT) $(INSTALLMLARGS)
-$(SHELL) ./installml.sh install "$(GUI_MAN_TARGETS)" \
$(DEST_MAN_IT_I) $(INSTALLMLARGS)
@@ -2006,6 +2021,9 @@ uninstall: uninstall_runtime
# Note: the "rmdir" will fail if any files were added after "make install"
uninstall_runtime:
-$(SHELL) ./installman.sh uninstall $(DEST_MAN) "" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh uninstall $(DEST_MAN_FR) "" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh uninstall $(DEST_MAN_FR_I) "" $(INSTALLMANARGS)
+ -$(SHELL) ./installman.sh uninstall $(DEST_MAN_FR_U) "" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh uninstall $(DEST_MAN_IT) "" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh uninstall $(DEST_MAN_IT_I) "" $(INSTALLMANARGS)
-$(SHELL) ./installman.sh uninstall $(DEST_MAN_IT_U) "" $(INSTALLMANARGS)
@@ -2014,6 +2032,12 @@ uninstall_runtime:
-$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
$(DEST_MAN) $(INSTALLMLARGS)
-$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR_I) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
+ $(DEST_MAN_FR_U) $(INSTALLMLARGS)
+ -$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
$(DEST_MAN_IT) $(INSTALLMLARGS)
-$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
$(DEST_MAN_IT_I) $(INSTALLMLARGS)
@@ -2024,6 +2048,7 @@ uninstall_runtime:
-$(SHELL) ./installml.sh uninstall "$(GUI_MAN_TARGETS)" \
$(DEST_MAN_RU_U) $(INSTALLMLARGS)
-rm -f $(DEST_MAN)/xxd.1
+ -rm -f $(DEST_MAN_FR)/xxd.1 $(DEST_MAN_FR_I)/xxd.1 $(DEST_MAN_FR_U)/xxd.1
-rm -f $(DEST_MAN_IT)/xxd.1 $(DEST_MAN_IT_I)/xxd.1 $(DEST_MAN_IT_U)/xxd.1
-rm -f $(DEST_MAN_RU)/xxd.1 $(DEST_MAN_RU_U)/xxd.1
-rm -f $(DEST_HELP)/*.txt $(DEST_HELP)/tags $(DEST_HELP)/*.pl
diff --git a/src/charset.c b/src/charset.c
index bd319ffe7c..a82a7264ba 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -972,6 +972,19 @@ init_spell_chartab()
}
#endif
#ifdef FEAT_MBYTE
+ else if (STRCMP(p_enc, "iso-8859-2") == 0)
+ {
+ /* latin2 */
+ for ( ; i <= 0xa0; ++i)
+ spell_chartab[i] = FALSE;
+ for ( ; i <= 255; ++i)
+ spell_chartab[i] = TRUE;
+ spell_chartab[0xa4] = FALSE; /* currency sign */
+ spell_chartab[0xa7] = FALSE; /* paragraph sign */
+ spell_chartab[0xad] = FALSE; /* dash */
+ spell_chartab[0xb0] = FALSE; /* degrees */
+ spell_chartab[0xf7] = FALSE; /* divide-by */
+ }
else
#endif
#if defined(FEAT_MBYTE) || !defined(MSDOS)
@@ -1117,6 +1130,7 @@ win_lbr_chartabsize(wp, s, col, headp)
int numberextra;
char_u *ps;
int tab_corr = (*s == TAB);
+ int n;
/*
* No 'linebreak' and 'showbreak': return quickly.
@@ -1160,9 +1174,12 @@ win_lbr_chartabsize(wp, s, col, headp)
col2 = col;
colmax = W_WIDTH(wp) - numberextra;
if (col >= colmax)
- colmax += (((col - colmax)
- / (colmax + win_col_off2(wp))) + 1)
- * (colmax + win_col_off2(wp));
+ {
+ n = colmax + win_col_off2(wp);
+ if (n > 0)
+ colmax += (((col - colmax) / n) + 1) * n;
+ }
+
for (;;)
{
ps = s;
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 5f79af92c7..76fafeff01 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -223,6 +223,9 @@ static void ex_popup __ARGS((exarg_T *eap));
#ifndef FEAT_SYN_HL
# define ex_syntax ex_ni
#endif
+#if !defined(FEAT_SYN_HL) || !defined(FEAT_MBYTE)
+# define ex_mkspell ex_ni
+#endif
#ifndef FEAT_MZSCHEME
# define ex_mzscheme ex_script_ni
# define ex_mzfile ex_ni
@@ -4149,11 +4152,11 @@ expand_filename(eap, cmdlinep, errormsgp)
/* For a shell command a '!' must be escaped. */
if ((eap->usefilter || eap->cmdidx == CMD_bang)
- && vim_strchr(repl, '!') != NULL)
+ && vim_strpbrk(repl, "!&;()") != NULL)
{
char_u *l;
- l = vim_strsave_escaped(repl, (char_u *)"!");
+ l = vim_strsave_escaped(repl, (char_u *)"!&;()");
if (l != NULL)
{
vim_free(repl);
@@ -7328,7 +7331,8 @@ ex_equal(eap)
ex_sleep(eap)
exarg_T *eap;
{
- int n;
+ int n;
+ long len;
if (cursor_valid())
{
@@ -7336,7 +7340,15 @@ ex_sleep(eap)
if (n >= 0)
windgoto((int)n, curwin->w_wcol);
}
- do_sleep(eap->line2 * (*eap->arg == 'm' ? 1L : 1000L));
+
+ len = eap->line2;
+ switch (*eap->arg)
+ {
+ case 'm': break;
+ case NUL: len *= 1000L; break;
+ default: EMSG2(_(e_invarg2), eap->arg); return;
+ }
+ do_sleep(len);
}
/*
diff --git a/src/fileio.c b/src/fileio.c
index a5e888abee..d88111a135 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2649,7 +2649,10 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit,
if (reset_changed
&& whole
&& buf == curbuf
- && curbuf->b_ffname == NULL
+#ifdef FEAT_QUICKFIX
+ && !bt_nofile(buf)
+#endif
+ && buf->b_ffname == NULL
&& !filtering
&& vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
{
diff --git a/src/gui.c b/src/gui.c
index 82124d0347..54804f71c0 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4326,17 +4326,18 @@ ex_gui(eap)
/*
* This is shared between Athena, Motif and GTK.
*/
-static char_u *gfp_buffer;
-
-static void gfp_setname __ARGS((char_u *fname));
+static void gfp_setname __ARGS((char_u *fname, void *cookie));
/*
* Callback function for do_in_runtimepath().
*/
static void
-gfp_setname(fname)
+gfp_setname(fname, cookie)
char_u *fname;
+ void *cookie;
{
+ char_u *gfp_buffer = cookie;
+
if (STRLEN(fname) >= MAXPATHL)
*gfp_buffer = NUL;
else
@@ -4356,8 +4357,8 @@ gui_find_bitmap(name, buffer, ext)
if (STRLEN(name) > MAXPATHL - 14)
return FAIL;
sprintf((char *)buffer, "bitmaps/%s.%s", name, ext);
- gfp_buffer = buffer;
- if (do_in_runtimepath(buffer, FALSE, gfp_setname) == FAIL || *buffer == NUL)
+ if (do_in_runtimepath(buffer, FALSE, gfp_setname, buffer) == FAIL
+ || *buffer == NUL)
return FAIL;
return OK;
}
diff --git a/src/gui_kde_x11.cc b/src/gui_kde_x11.cc
index 3bb80765ac..21969c5861 100644
--- a/src/gui_kde_x11.cc
+++ b/src/gui_kde_x11.cc
@@ -970,10 +970,20 @@ gui_mch_draw_part_cursor(int w, int h, guicolor_T color)//{{{
QPainter p(gui.w);
p.setPen(color);
p.fillRect(
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
FILL_X(gui.col),
FILL_Y(gui.row) + gui.char_height - h + 1,
w, h - 2, QColor( color, color));
- p.drawRect(FILL_X(gui.col), FILL_Y(gui.row) + gui.char_height - h
+ p.drawRect(
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col),
+ FILL_Y(gui.row) + gui.char_height - h
+ (int)p_linespace / 2,
w, h - (int)p_linespace);
}//}}}
diff --git a/src/gui_w32.c b/src/gui_w32.c
index 50c5e59397..e83ff40602 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -1794,7 +1794,7 @@ gui_mch_draw_string(
#ifdef FEAT_MBYTE
static WCHAR *unicodebuf = NULL;
static int *unicodepdy = NULL;
- int unibuflen = 0;
+ static int unibuflen = 0;
int n = 0;
#endif
HPEN hpen, old_pen;
@@ -1923,7 +1923,7 @@ gui_mch_draw_string(
break;
/* Check if the Unicode buffer exists and is big enough. Create it
- * with the same lengt as the multi-byte string, the number of wide
+ * with the same length as the multi-byte string, the number of wide
* characters is always equal or smaller. */
if ((enc_utf8
|| (enc_codepage > 0 && (int)GetACP() != enc_codepage)
diff --git a/src/macros.h b/src/macros.h
index 233df0f25c..f7bb10dca3 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -260,8 +260,10 @@
# define mb_ptr_adv(p) p += has_mbyte ? (*mb_ptr2len_check)(p) : 1
# define mb_ptr_back(s, p) p -= has_mbyte ? ((*mb_head_off)(s, p - 1) + 1) : 1
# define MB_COPY_CHAR(f, t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++
+# define MB_CHARLEN(p) mb_charlen(p)
#else
# define mb_ptr_adv(p) ++p
# define mb_ptr_back(s, p) --p
# define MB_COPY_CHAR(f, t) *t++ = *f++
+# define MB_CHARLEN(p) STRLEN(p)
#endif
diff --git a/src/mbyte.c b/src/mbyte.c
index 7f8400d5cd..70bb843892 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -706,6 +706,11 @@ codepage_invalid:
gui_mch_update_codec();
#endif
+#ifdef FEAT_SYN_HL
+ /* Need to reload spell dictionaries */
+ spell_reload();
+#endif
+
return NULL;
}
diff --git a/src/misc2.c b/src/misc2.c
index c8952074cd..0735e29636 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -5241,7 +5241,8 @@ qsort(base, elm_count, elm_size, cmp)
}
#endif
-#if defined(FEAT_EX_EXTRA) || defined(FEAT_CMDL_COMPL) || defined(PROTO)
+#if defined(FEAT_EX_EXTRA) || defined(FEAT_CMDL_COMPL) \
+ || (defined(FEAT_SYN_HL) && defined(FEAT_MBYTE)) || defined(PROTO)
/*
* Sort an array of strings.
*/
diff --git a/src/normal.c b/src/normal.c
index fb6f8f9819..85d84c45be 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -6065,6 +6065,18 @@ nv_brackets(cap)
}
#endif
+#ifdef FEAT_SYN_HL
+ /*
+ * "[s", "[S", "]s" and "]S": move to next spell error.
+ */
+ else if (cap->nchar == 's' || cap->nchar == 'S')
+ {
+ if (spell_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
+ cap->nchar == 's' ? TRUE : FALSE) == FAIL)
+ clearopbeep(cap->oap);
+ }
+#endif
+
/* Not a valid cap->nchar. */
else
clearopbeep(cap->oap);
@@ -8493,6 +8505,7 @@ nv_put(cap)
int regname = 0;
void *reg1 = NULL, *reg2 = NULL;
int empty = FALSE;
+ int was_visual = FALSE;
#endif
int dir;
int flags = 0;
@@ -8527,6 +8540,7 @@ nv_put(cap)
* Need to save and restore the registers that the delete
* overwrites if the old contents is being put.
*/
+ was_visual = TRUE;
regname = cap->oap->regname;
# ifdef FEAT_CLIPBOARD
adjust_clip_reg(&regname);
@@ -8587,8 +8601,17 @@ nv_put(cap)
/* If a register was saved, put it back now. */
if (reg2 != NULL)
put_register(regname, reg2);
+
+ /* What to reselect with "gv"? Selecting the just put text seems to
+ * be the most useful, since the original text was removed. */
+ if (was_visual)
+ {
+ curbuf->b_visual_start = curbuf->b_op_start;
+ curbuf->b_visual_end = curbuf->b_op_end;
+ }
+
/* When all lines were selected and deleted do_put() leaves an empty
- * line that needs to delete now. */
+ * line that needs to be deleted now. */
if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL)
ml_delete(curbuf->b_ml.ml_line_count, TRUE);
#endif
diff --git a/src/os_unix.c b/src/os_unix.c
index afe9bfdc06..80735b69a0 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5177,6 +5177,8 @@ mch_expand_wildcards(num_pat, pat, num_file, file, flags)
else if (!intick && vim_strchr((char_u *)" '",
pat[i][j]) != NULL)
{
+ /* Put quotes around special characters, but not when
+ * inside ``. */
*p++ = '"';
while (pat[i][j] != NUL
&& vim_strchr((char_u *)" '", pat[i][j]) != NULL)
diff --git a/src/quickfix.c b/src/quickfix.c
index a4c016e09a..e022c787a5 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2338,11 +2338,9 @@ ex_vimgrep(eap)
char_u **fnames;
char_u *s;
char_u *p;
- int i;
int fi;
qfline_T *prevp = NULL;
long lnum;
- garray_T ga;
buf_T *buf;
int duplicate_name = FALSE;
int using_dummy;
@@ -2404,12 +2402,7 @@ ex_vimgrep(eap)
;
/* parse the list of arguments */
- if (get_arglist(&ga, p) == FAIL)
- goto theend;
- i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
- &fcount, &fnames, EW_FILE|EW_NOTFOUND);
- ga_clear(&ga);
- if (i == FAIL)
+ if (get_arglist_exp(p, &fcount, &fnames) == FAIL)
goto theend;
if (fcount == 0)
{
diff --git a/src/regexp.c b/src/regexp.c
index fe20b3a8fb..8a2643dcce 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -738,65 +738,69 @@ reg_equi_class(c)
{
switch (c)
{
- case 'A': case 'À': case 'Á': case 'Â':
- case 'Ã': case 'Ä': case 'Å':
- regmbc('A'); regmbc('À'); regmbc('Á'); regmbc('Â');
- regmbc('Ã'); regmbc('Ä'); regmbc('Å');
+ case 'A': case '\300': case '\301': case '\302':
+ case '\303': case '\304': case '\305':
+ regmbc('A'); regmbc('\300'); regmbc('\301');
+ regmbc('\302'); regmbc('\303'); regmbc('\304');
+ regmbc('\305');
return;
- case 'C': case 'Ç':
- regmbc('C'); regmbc('Ç');
+ case 'C': case '\307':
+ regmbc('C'); regmbc('\307');
return;
- case 'E': case 'È': case 'É': case 'Ê': case 'Ë':
- regmbc('E'); regmbc('È'); regmbc('É'); regmbc('Ê');
- regmbc('Ë');
+ case 'E': case '\310': case '\311': case '\312': case '\313':
+ regmbc('E'); regmbc('\310'); regmbc('\311');
+ regmbc('\312'); regmbc('\313');
return;
- case 'I': case 'Ì': case 'Í': case 'Î': case 'Ï':
- regmbc('I'); regmbc('Ì'); regmbc('Í'); regmbc('Î');
- regmbc('Ï');
+ case 'I': case '\314': case '\315': case '\316': case '\317':
+ regmbc('I'); regmbc('\314'); regmbc('\315');
+ regmbc('\316'); regmbc('\317');
return;
- case 'N': case 'Ñ':
- regmbc('N'); regmbc('Ñ');
+ case 'N': case '\321':
+ regmbc('N'); regmbc('\321');
return;
- case 'O': case 'Ò': case 'Ó': case 'Ô': case 'Õ': case 'Ö':
- regmbc('O'); regmbc('Ò'); regmbc('Ó'); regmbc('Ô');
- regmbc('Õ'); regmbc('Ö');
+ case 'O': case '\322': case '\323': case '\324': case '\325':
+ case '\326':
+ regmbc('O'); regmbc('\322'); regmbc('\323');
+ regmbc('\324'); regmbc('\325'); regmbc('\326');
return;
- case 'U': case 'Ù': case 'Ú': case 'Û': case 'Ü':
- regmbc('U'); regmbc('Ù'); regmbc('Ú'); regmbc('Û');
- regmbc('Ü');
+ case 'U': case '\331': case '\332': case '\333': case '\334':
+ regmbc('U'); regmbc('\331'); regmbc('\332');
+ regmbc('\333'); regmbc('\334');
return;
- case 'Y': case 'Ý':
- regmbc('Y'); regmbc('Ý');
+ case 'Y': case '\335':
+ regmbc('Y'); regmbc('\335');
return;
- case 'a': case 'à': case 'á': case 'â':
- case 'ã': case 'ä': case 'å':
- regmbc('a'); regmbc('à'); regmbc('á'); regmbc('â');
- regmbc('ã'); regmbc('ä'); regmbc('å');
+ case 'a': case '\340': case '\341': case '\342':
+ case '\343': case '\344': case '\345':
+ regmbc('a'); regmbc('\340'); regmbc('\341');
+ regmbc('\342'); regmbc('\343'); regmbc('\344');
+ regmbc('\345');
return;
- case 'c': case 'ç':
- regmbc('c'); regmbc('ç');
+ case 'c': case '\347':
+ regmbc('c'); regmbc('\347');
return;
- case 'e': case 'è': case 'é': case 'ê': case 'ë':
- regmbc('e'); regmbc('è'); regmbc('é'); regmbc('ê');
- regmbc('ë');
+ case 'e': case '\350': case '\351': case '\352': case '\353':
+ regmbc('e'); regmbc('\350'); regmbc('\351');
+ regmbc('\352'); regmbc('\353');
return;
- case 'i': case 'ì': case 'í': case 'î': case 'ï':
- regmbc('i'); regmbc('ì'); regmbc('í'); regmbc('î');
- regmbc('ï');
+ case 'i': case '\354': case '\355': case '\356': case '\357':
+ regmbc('i'); regmbc('\354'); regmbc('\355');
+ regmbc('\356'); regmbc('\357');
return;
- case 'n': case 'ñ':
- regmbc('n'); regmbc('ñ');
+ case 'n': case '\361':
+ regmbc('n'); regmbc('\361');
return;
- case 'o': case 'ò': case 'ó': case 'ô': case 'õ': case 'ö':
- regmbc('o'); regmbc('ò'); regmbc('ó'); regmbc('ô');
- regmbc('õ'); regmbc('ö');
+ case 'o': case '\362': case '\363': case '\364': case '\365':
+ case '\366':
+ regmbc('o'); regmbc('\362'); regmbc('\363');
+ regmbc('\364'); regmbc('\365'); regmbc('\366');
return;
- case 'u': case 'ù': case 'ú': case 'û': case 'ü':
- regmbc('u'); regmbc('ù'); regmbc('ú'); regmbc('û');
- regmbc('ü');
+ case 'u': case '\371': case '\372': case '\373': case '\374':
+ regmbc('u'); regmbc('\371'); regmbc('\372');
+ regmbc('\373'); regmbc('\374');
return;
- case 'y': case 'ý': case 'ÿ':
- regmbc('y'); regmbc('ý'); regmbc('ÿ');
+ case 'y': case '\375': case '\377':
+ regmbc('y'); regmbc('\375'); regmbc('\377');
return;
}
}
diff --git a/src/screen.c b/src/screen.c
index 70c7ff1894..b2e1181275 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3605,7 +3605,7 @@ win_line(wp, lnum, startrow, endrow)
iswordc = spell_iswordc(prev_ptr);
if (iswordc && !prev_iswordc)
{
- word_end = v + spell_check(wp, prev_ptr,
+ word_end = v + spell_check(wp, line, prev_ptr,
&spell_attr);
/* In Insert mode only highlight a word that
* doesn't touch the cursor. */
@@ -8002,7 +8002,7 @@ showmode()
if (gui.in_use)
{
if (hangul_input_state_get())
- MSG_PUTS_ATTR(" ÇѱÛ", attr); /* HANGUL */
+ MSG_PUTS_ATTR(" \307\321\261\333", attr); /* HANGUL */
}
#endif
#ifdef FEAT_INS_EXPAND
diff --git a/src/spell.c b/src/spell.c
index 30a02ab41f..e3a97fc833 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -16,6 +16,11 @@
* "word" is either a "dword" or an "nword".
*/
+/*
+ * Why doesn't Vim use aspell/ispell/myspell/etc.?
+ * See ":help develop-spell".
+ */
+
#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
# include <io.h> /* for lseek(), must be before vim.h */
#endif
@@ -32,8 +37,3860 @@
/*
* Structure that is used to store the text from the language file. This
- * avoids the need to allocate each individual word and copying it. It's
- * allocated in big chunks for speed.
+ * 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 */
+};
+
+/* Info from "REP" entries in ".aff" file used in af_rep. */
+typedef struct repentry_S
+{
+ char_u *re_from;
+ char_u *re_to;
+} repentry_T;
+
+/*
+ * Structure to store affix info.
+ */
+typedef struct affitem_S affitem_T;
+struct affitem_S
+{
+ affitem_T *ai_next; /* next affix with same ai_add[] or NULL */
+ short_u ai_nr; /* affix number */
+ char_u ai_combine; /* prefix combines with suffix */
+ char_u ai_choplen; /* length of ai_chop in bytes */
+ char_u ai_addlen; /* length of ai_add in bytes */
+ char_u *ai_chop; /* text chopped off basic word (can be NULL) */
+ char_u ai_add[1]; /* text added to basic word (actually longer) */
+};
+
+/* Get affitem_T pointer from hashitem that uses ai_add */
+static affitem_T dumai;
+#define HI2AI(hi) ((affitem_T *)((hi)->hi_key - (dumai.ai_add - (char_u *)&dumai)))
+
+/*
+ * 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; /* language name "en", "en.rare", "nl", etc. */
+ hashtab_T sl_words; /* main word table, fword_T */
+ int sl_prefcnt; /* number of prefix NRs */
+ garray_T sl_preftab; /* list of hashtables to lookup prefixes */
+ affitem_T *sl_prefzero; /* list of prefixes with zero add length */
+ int sl_suffcnt; /* number of suffix NRs */
+ garray_T sl_sufftab; /* list of hashtables to lookup suffixes */
+ affitem_T *sl_suffzero; /* list of suffixes with zero add length */
+ char_u *sl_try; /* "TRY" from .aff file */
+ garray_T sl_rep; /* list of repentry_T entries from REP lines */
+ char_u sl_regions[17]; /* table with up to 8 region names plus NUL */
+ sblock_T *sl_block; /* list with allocated memory blocks */
+ int sl_error; /* error while loading */
+};
+
+static slang_T *first_lang = NULL;
+
+/*
+ * Structure to store an addition to a basic word.
+ */
+typedef struct addword_S addword_T;
+struct addword_S
+{
+ addword_T *aw_next; /* next addition */
+ char_u aw_flags; /* ADD_ flags */
+ char_u aw_leadlen; /* length of lead in bytes */
+ char_u aw_wordlen; /* length of aw_word in bytes */
+ char_u aw_region; /* region for word with this addition */
+ char_u aw_word[1]; /* text, actually longer: case-folded addition
+ plus, with ADD_KEEPCAP: keep-case addition */
+};
+
+/*
+ * Structure to store a basic word.
+ */
+typedef struct fword_S fword_T;
+struct fword_S
+{
+ fword_T *fw_next; /* same basic word with different caps */
+ char_u fw_region; /* region bits */
+ char_u fw_prefixcnt; /* number of prefix numbers */
+ char_u fw_suffixcnt; /* number of suffix numbers */
+ short_u fw_flags; /* BWF_ flags */
+ void *fw_prefix; /* table with prefix numbers */
+ void *fw_suffix; /* table with suffix numbers */
+ addword_T *fw_adds; /* first addword_T entry */
+ char_u fw_word[1]; /* actually longer: case folded word, or
+ keep-case word when (flags & BWF_KEEPCAP) */
+};
+
+/* Get fword_T pointer from hashitem that uses fw_word */
+static fword_T dumfw;
+#define HI2FWORD(hi) ((fword_T *)((hi)->hi_key - (dumfw.fw_word - (char_u *)&dumfw)))
+
+#define REGION_ALL 0xff
+
+
+/*
+ * 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 SP_OK 0
+#define SP_BAD 1
+#define SP_RARE 2
+#define SP_LOCAL 3
+
+/* flags used for basic words in the spell file */
+#define BWF_VALID 0x01 /* word is valid without additions */
+#define BWF_REGION 0x02 /* region byte follows */
+#define BWF_ONECAP 0x04 /* first letter must be capital */
+#define BWF_SUFFIX 0x08 /* has suffix NR list */
+#define BWF_SECOND 0x10 /* second flags byte follows */
+
+#define BWF_ADDS 0x0100 /* there are additions */
+#define BWF_PREFIX 0x0200 /* has prefix NR list */
+#define BWF_ALLCAP 0x0400 /* all letters must be capital (not used
+ for single-letter words) */
+#define BWF_KEEPCAP 0x0800 /* Keep case as-is */
+
+/* flags used for addition in the spell file */
+#define ADD_REGION 0x02 /* region byte follows */
+#define ADD_ONECAP 0x04 /* first letter must be capital */
+#define ADD_ALLCAP 0x40 /* all letters must be capital (not used
+ for single-letter words) */
+#define ADD_KEEPCAP 0x80 /* fixed case */
+
+/* Translate ADD_ flags to BWF_ flags.
+ * (Needed to keep ADD_ flags in one byte.) */
+#define ADD2BWF(x) (((x) & 0x0f) | (((x) & 0xf0) << 4))
+
+#define VIMSPELLMAGIC "VIMspell01" /* string at start of Vim spell file */
+#define VIMSPELLMAGICL 10
+
+/*
+ * Structure to store info for word matching.
+ */
+typedef struct matchinf_S
+{
+ langp_T *mi_lp; /* info for language and region */
+ slang_T *mi_slang; /* info for the language */
+ char_u *mi_line; /* start of line containing word */
+ char_u *mi_word; /* start of word being checked */
+ char_u *mi_end; /* first non-word char after mi_word */
+ char_u *mi_wend; /* end of matching word (is "mi_end"
+ * or further) */
+ char_u *mi_cword; /* word to check, can be "mi_fword" */
+ char_u mi_fword[MAXWLEN + 1]; /* "mi_word" to "mi_end" case-folded */
+ int mi_faddlen; /* length of valid bytes in "mi_fadd" */
+ char_u *mi_faddp; /* next char to be added to "mi_fadd" */
+ char_u mi_fadd[MAXWLEN + 1]; /* "mi_end" and further case-folded */
+ int mi_result; /* result so far: SP_BAD, SP_OK, etc. */
+ int mi_capflags; /* BWF_ONECAP BWF_ALLCAP BWF_KEEPCAP */
+} matchinf_T;
+
+static int word_match __ARGS((matchinf_T *mip));
+static int check_adds __ARGS((matchinf_T *mip, fword_T *fw, int req_pref, int req_suf));
+static int supports_afffix __ARGS((int cnt, void *afffix, int afffixcnt, int nr));
+static int prefix_match __ARGS((matchinf_T *mip));
+static int suffix_match __ARGS((matchinf_T *mip));
+static int match_caps __ARGS((int flags, char_u *caseword, matchinf_T *mip, char_u *cword, char_u *end));
+static slang_T *slang_alloc __ARGS((char_u *lang));
+static void slang_free __ARGS((slang_T *lp));
+static slang_T *spell_load_lang __ARGS((char_u *lang));
+static void spell_load_file __ARGS((char_u *fname, void *cookie));
+static int spell_load_affixes __ARGS((FILE *fd, slang_T *lp, int *bl_usedp, int affm, void **affp));
+static void *getroom __ARGS((slang_T *lp, int *bl_used, int len));
+static int find_region __ARGS((char_u *rp, char_u *region));
+static int captype __ARGS((char_u *word, char_u *end));
+
+/*
+ * 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.
+ */
+ int
+spell_check(wp, line, ptr, attrp)
+ win_T *wp; /* current window */
+ char_u *line; /* start of line where "ptr" points into */
+ char_u *ptr;
+ int *attrp;
+{
+ matchinf_T mi; /* Most things are put in "mi" so that it can
+ be passed to functions quickly. */
+
+ /* Find the end of the word. We already know that *ptr is a word char. */
+ mi.mi_word = ptr;
+ mi.mi_end = ptr;
+ do
+ {
+ mb_ptr_adv(mi.mi_end);
+ } while (*mi.mi_end != NUL && spell_iswordc(mi.mi_end));
+
+ /* A word starting with a number is always OK. */
+ if (*ptr >= '0' && *ptr <= '9')
+ return (int)(mi.mi_end - ptr);
+
+ /* Make case-folded copy of the Word. Compute its hash value. */
+ (void)str_foldcase(ptr, mi.mi_end - ptr, mi.mi_fword, MAXWLEN + 1);
+ mi.mi_cword = mi.mi_fword;
+
+ /* The word is bad unless we find it in the dictionary. */
+ mi.mi_result = SP_BAD;
+ mi.mi_wend = mi.mi_end;
+ mi.mi_faddp = mi.mi_end;
+ mi.mi_faddlen = 0;
+ mi.mi_capflags = captype(ptr, mi.mi_end);
+ mi.mi_line = line;
+
+ /*
+ * Loop over the languages specified in 'spelllang'.
+ * We check them all, because a matching word may have additions that are
+ * longer than an already found matching word.
+ */
+ for (mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
+ mi.mi_lp->lp_slang != NULL; ++mi.mi_lp)
+ {
+ /*
+ * Check for a matching word.
+ * If not found or wrong region try removing prefixes (and then
+ * suffixes).
+ * If still not found or wrong region try removing suffixes.
+ */
+ mi.mi_slang = mi.mi_lp->lp_slang;
+ if (!word_match(&mi) || mi.mi_result != SP_OK)
+ if (!prefix_match(&mi) || mi.mi_result != SP_OK)
+ suffix_match(&mi);
+ }
+
+ if (mi.mi_result != SP_OK)
+ {
+ if (mi.mi_result == SP_BAD)
+ *attrp = highlight_attr[HLF_SPB];
+ else if (mi.mi_result == SP_RARE)
+ *attrp = highlight_attr[HLF_SPR];
+ else
+ *attrp = highlight_attr[HLF_SPL];
+ }
+
+ return (int)(mi.mi_wend - ptr);
+}
+
+/*
+ * Check if the word "mip->mi_cword" matches.
+ */
+ static int
+word_match(mip)
+ matchinf_T *mip;
+{
+ hash_T fhash = hash_hash(mip->mi_cword);
+ hashitem_T *hi;
+ fword_T *fw;
+ int valid = FALSE;
+
+ hi = hash_lookup(&mip->mi_slang->sl_words, mip->mi_cword, fhash);
+ if (HASHITEM_EMPTY(hi))
+ return FALSE;
+
+ /*
+ * Find a basic word for which the case of word "cword" is correct.
+ * If it is, check additions and use the longest one.
+ */
+ for (fw = HI2FWORD(hi); fw != NULL; fw = fw->fw_next)
+ if (match_caps(fw->fw_flags, fw->fw_word, mip,
+ mip->mi_word, mip->mi_end))
+ valid |= check_adds(mip, fw, -1, -1);
+
+ return valid;
+}
+
+/*
+ * Check a matching basic word for additions.
+ * Return TRUE if we have a valid match.
+ */
+ static int
+check_adds(mip, fw, req_pref, req_suf)
+ matchinf_T *mip;
+ fword_T *fw;
+ int req_pref; /* required prefix nr, -1 if none */
+ int req_suf; /* required suffix nr, -1 if none */
+{
+ int valid = FALSE;
+ addword_T *aw;
+ char_u *p;
+ int addlen;
+ int fl;
+
+ /* A word may be valid without additions. */
+ if ((fw->fw_flags & BWF_VALID)
+ && (req_pref < 0 || supports_afffix(mip->mi_slang->sl_prefcnt,
+ fw->fw_prefix, fw->fw_prefixcnt, req_pref))
+ &&