diff options
author | Bram Moolenaar <Bram@vim.org> | 2005-09-29 18:26:07 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2005-09-29 18:26:07 +0000 |
commit | 482aaeb058a3c05235148d22f6c511416da009fb (patch) | |
tree | b9c63e97ec2826bfeea041afe176a04763dbcfa8 /src | |
parent | 4463f296d0744915fa25dbd893821833043f9a25 (diff) | |
download | vim-git-482aaeb058a3c05235148d22f6c511416da009fb.tar.gz |
updated for version 7.0151v7.0151
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.c | 26 | ||||
-rw-r--r-- | src/ex_cmds2.c | 8 | ||||
-rw-r--r-- | src/ex_docmd.c | 12 | ||||
-rw-r--r-- | src/ex_getln.c | 10 | ||||
-rw-r--r-- | src/globals.h | 5 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/normal.c | 3 | ||||
-rw-r--r-- | src/option.c | 7 | ||||
-rw-r--r-- | src/proto/spell.pro | 4 | ||||
-rw-r--r-- | src/screen.c | 54 | ||||
-rw-r--r-- | src/search.c | 23 | ||||
-rw-r--r-- | src/spell.c | 308 | ||||
-rw-r--r-- | src/testdir/test58.ok | 8 | ||||
-rw-r--r-- | src/testdir/test59.ok | 8 | ||||
-rw-r--r-- | src/ui.c | 11 | ||||
-rw-r--r-- | src/version.h | 4 | ||||
-rw-r--r-- | src/vim.h | 4 |
17 files changed, 320 insertions, 181 deletions
diff --git a/src/eval.c b/src/eval.c index 206bbfbfa..e5212111e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5571,8 +5571,8 @@ list_append_string(l, str, len) list_append(l, li); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; - if ((li->li_tv.vval.v_string = len >= 0 ? vim_strnsave(str, len) - : vim_strsave(str)) == NULL) + if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len) + : vim_strsave(str))) == NULL) return FAIL; return OK; } @@ -8271,7 +8271,7 @@ f_diff_hlID(argvars, rettv) static int fnum = 0; static int change_start = 0; static int change_end = 0; - static enum hlf_value hlID = 0; + static hlf_T hlID = 0; int filler_lines; int col; @@ -8298,7 +8298,7 @@ f_diff_hlID(argvars, rettv) hlID = HLF_ADD; /* added line */ } else - hlID = (enum hlf_value)0; + hlID = (hlf_T)0; prev_lnum = lnum; changedtick = curbuf->b_changedtick; fnum = curbuf->b_fnum; @@ -8312,7 +8312,7 @@ f_diff_hlID(argvars, rettv) else hlID = HLF_CHD; /* changed line */ } - rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID; + rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID; #endif } @@ -13902,8 +13902,8 @@ f_spellbadword(argvars, rettv) { char_u *word = (char_u *)""; #ifdef FEAT_SYN_HL - int len; - int attr = 0; + int len = 0; + hlf_T attr = HLF_COUNT; list_T *l; #endif @@ -13933,7 +13933,7 @@ f_spellbadword(argvars, rettv) while (*str != NUL) { len = spell_check(curwin, str, &attr, &capcol); - if (attr != 0) + if (attr != HLF_COUNT) { word = str; break; @@ -13946,11 +13946,11 @@ f_spellbadword(argvars, rettv) list_append_string(l, word, len); list_append_string(l, (char_u *)( - attr == highlight_attr[HLF_SPB] ? "bad" : - attr == highlight_attr[HLF_SPR] ? "rare" : - attr == highlight_attr[HLF_SPL] ? "local" : - attr == highlight_attr[HLF_SPC] ? "caps" : - ""), -1); + attr == HLF_SPB ? "bad" : + attr == HLF_SPR ? "rare" : + attr == HLF_SPL ? "local" : + attr == HLF_SPC ? "caps" : + ""), -1); } /* diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index c635bfc4c..449b66c37 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -3901,7 +3901,15 @@ ex_language(eap) * FEAT_GETTEXT isn't defined, so that shell commands use this * value. */ if (what == LC_ALL) + { vim_setenv((char_u *)"LANG", name); +# ifdef WIN32 + /* Apparently MS-Windows printf() may cause a crash when + * we give it 8-bit text while it's expecting text in the + * current locale. This call avoids that. */ + setlocale(LC_CTYPE, "C"); +# endif + } if (what != LC_CTYPE) { char_u *mname; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index f88fbf815..724238179 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5900,7 +5900,7 @@ parse_compl_arg(value, vallen, complp, argt, compl_arg) for (i = 0; command_complete[i].expand != 0; ++i) { - if (STRLEN(command_complete[i].name) == valend + if ((int)STRLEN(command_complete[i].name) == valend && STRNCMP(value, command_complete[i].name, valend) == 0) { *complp = command_complete[i].expand; @@ -9179,15 +9179,21 @@ makeopens(fd, dirnow) */ if (ssop_flags & SSOP_SESDIR) { - if (put_line(fd, "exe \"cd \" . expand(\"<sfile>:p:h\")") == FAIL) + if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')") + == FAIL) return FAIL; } else if (ssop_flags & SSOP_CURDIR) { sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow); if (sname == NULL - || fprintf(fd, "cd %s", sname) < 0 || put_eol(fd) == FAIL) + || fputs("cd ", fd) < 0 + || ses_put_fname(fd, sname, &ssop_flags) == FAIL + || put_eol(fd) == FAIL) + { + vim_free(sname); return FAIL; + } vim_free(sname); } diff --git a/src/ex_getln.c b/src/ex_getln.c index a3fac10ac..2748915be 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1700,7 +1700,7 @@ cmdline_changed: #ifdef FEAT_RIGHTLEFT if (cmdmsg_rl # ifdef FEAT_ARABIC - || p_arshape + || (p_arshape && !p_tbidi && enc_utf8) # endif ) /* Always redraw the whole command line to fix shaping and @@ -1873,7 +1873,11 @@ set_cmdspos_cursor() set_cmdspos(); if (KeyTyped) + { m = Columns * Rows; + if (m < 0) /* overflow, Columns or Rows at weird value */ + m = MAXCOL; + } else m = MAXCOL; for (i = 0; i < ccline.cmdlen && i < ccline.cmdpos; ++i) @@ -2641,7 +2645,11 @@ put_on_cmdline(str, len, redraw) #endif { if (KeyTyped) + { m = Columns * Rows; + if (m < 0) /* overflow, Columns or Rows at weird value */ + m = MAXCOL; + } else m = MAXCOL; for (i = 0; i < len; ++i) diff --git a/src/globals.h b/src/globals.h index 4b916efd8..3731f0673 100644 --- a/src/globals.h +++ b/src/globals.h @@ -35,6 +35,9 @@ EXTERN long Columns INIT(= 80); /* nr of columns in the screen */ * * "LineOffset[n]" is the offset from ScreenLines[] for the start of line 'n'. * The same value is used for ScreenLinesUC[] and ScreenAttrs[]. + * + * Note: before the screen is initialized and when out of memory these can be + * NULL. */ EXTERN schar_T *ScreenLines INIT(= NULL); EXTERN sattr_T *ScreenAttrs INIT(= NULL); @@ -818,7 +821,7 @@ EXTERN int ins_at_eol INIT(= FALSE); /* put cursor after eol when EXTERN char_u *edit_submode INIT(= NULL); /* msg for CTRL-X submode */ EXTERN char_u *edit_submode_pre INIT(= NULL); /* prepended to edit_submode */ EXTERN char_u *edit_submode_extra INIT(= NULL);/* appended to edit_submode */ -EXTERN enum hlf_value edit_submode_highl; /* highl. method for extra info */ +EXTERN hlf_T edit_submode_highl; /* highl. method for extra info */ EXTERN int ctrl_x_mode INIT(= 0); /* Which Ctrl-X mode are we in? */ #endif diff --git a/src/main.c b/src/main.c index 898205e28..f7e2b1bb9 100644 --- a/src/main.c +++ b/src/main.c @@ -1236,6 +1236,12 @@ get_number_arg(p, idx, def) init_locale() { setlocale(LC_ALL, ""); +# ifdef WIN32 + /* Apparently MS-Windows printf() may cause a crash when we give it 8-bit + * text while it's expecting text in the current locale. This call avoids + * that. */ + setlocale(LC_CTYPE, "C"); +# endif # ifdef FEAT_GETTEXT { diff --git a/src/normal.c b/src/normal.c index 84de270ea..1e645e447 100644 --- a/src/normal.c +++ b/src/normal.c @@ -4750,10 +4750,9 @@ dozet: if (ptr == NULL) { pos_T pos = curwin->w_cursor; - int attr; /* Find bad word under the cursor. */ - len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr); + len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL); if (len != 0 && curwin->w_cursor.col <= pos.col) ptr = ml_get_pos(&curwin->w_cursor); curwin->w_cursor = pos; diff --git a/src/option.c b/src/option.c index d547edc1e..b3c80d6a4 100644 --- a/src/option.c +++ b/src/option.c @@ -3277,6 +3277,7 @@ set_init_2() * "linux" Linux console * "screen.linux" Linux console with screen * "cygwin" Cygwin shell + * "putty" Putty program * We also check the COLORFGBG environment variable, which is set by * rxvt and derivatives. This variable contains either two or three * values separated by semicolons; we want the last value in either @@ -3287,6 +3288,7 @@ set_init_2() && (STRCMP(T_NAME, "linux") == 0 || STRCMP(T_NAME, "screen.linux") == 0 || STRCMP(T_NAME, "cygwin") == 0 + || STRCMP(T_NAME, "putty") == 0 || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL && (p = vim_strrchr(p, ';')) != NULL && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8') @@ -7343,6 +7345,11 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags) } Columns = MIN_COLUMNS; } + /* Limit the values to avoid an overflow in Rows * Columns. */ + if (Columns > 10000) + Columns = 10000; + if (Rows > 1000) + Rows = 1000; #ifdef DJGPP /* avoid a crash by checking for a too large value of 'columns' */ diff --git a/src/proto/spell.pro b/src/proto/spell.pro index 2adc137e9..facbfbc76 100644 --- a/src/proto/spell.pro +++ b/src/proto/spell.pro @@ -1,6 +1,6 @@ /* spell.c */ -int spell_check __ARGS((win_T *wp, char_u *ptr, int *attrp, int *capcol)); -int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, int *attrp)); +int spell_check __ARGS((win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol)); +int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, hlf_T *attrp)); void spell_cat_line __ARGS((char_u *buf, char_u *line, int maxlen)); char_u *did_set_spelllang __ARGS((buf_T *buf)); void spell_free_all __ARGS((void)); diff --git a/src/screen.c b/src/screen.c index f497f370d..fa1390424 100644 --- a/src/screen.c +++ b/src/screen.c @@ -128,7 +128,7 @@ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ static schar_T *current_ScreenLine; static void win_update __ARGS((win_T *wp)); -static void win_draw_end __ARGS((win_T *wp, int c1, int c2, int row, int endrow, enum hlf_value hl)); +static void win_draw_end __ARGS((win_T *wp, int c1, int c2, int row, int endrow, hlf_T hl)); #ifdef FEAT_FOLDING static void fold_line __ARGS((win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row)); static void fill_foldcolumn __ARGS((char_u *p, win_T *wp, int closed, linenr_T lnum)); @@ -1904,7 +1904,7 @@ win_draw_end(wp, c1, c2, row, endrow, hl) int c2; int row; int endrow; - enum hlf_value hl; + hlf_T hl; { #if defined(FEAT_FOLDING) || defined(FEAT_SIGNS) || defined(FEAT_CMDWIN) int n = 0; @@ -2531,7 +2531,7 @@ win_line(wp, lnum, startrow, endrow) #ifdef FEAT_DIFF int filler_lines; /* nr of filler lines to be drawn */ int filler_todo; /* nr of filler lines still to do + 1 */ - enum hlf_value diff_hlf = (enum hlf_value)0; /* type of diff highlighting */ + hlf_T diff_hlf = (hlf_T)0; /* type of diff highlighting */ int change_start = MAXCOL; /* first col of changed area */ int change_end = -1; /* last col of changed area */ #endif @@ -2926,22 +2926,28 @@ win_line(wp, lnum, startrow, endrow) if (has_spell) { int len; + hlf_T spell_hlf = HLF_COUNT; pos = wp->w_cursor; wp->w_cursor.lnum = lnum; wp->w_cursor.col = ptr - line; - len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_attr); + len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf); if (len == 0 || (int)wp->w_cursor.col > ptr - line) { /* no bad word found at line start, don't check until end of a * word */ - spell_attr = 0; + spell_hlf = HLF_COUNT; word_end = spell_to_word_end(ptr, wp->w_buffer) - line + 1; } else + { /* bad word found, use attributes until end of word */ word_end = wp->w_cursor.col + len + 1; + /* Turn index into actual attributes. */ + if (spell_hlf != HLF_COUNT) + spell_attr = highlight_attr[spell_hlf]; + } wp->w_cursor = pos; /* Need to restart syntax highlighting for this line. */ @@ -3353,7 +3359,7 @@ win_line(wp, lnum, startrow, endrow) char_attr = search_attr; #ifdef FEAT_DIFF - if (diff_hlf != (enum hlf_value)0 && n_extra == 0) + if (diff_hlf != (hlf_T)0 && n_extra == 0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start) diff_hlf = HLF_TXD; /* changed text */ @@ -3719,6 +3725,7 @@ win_line(wp, lnum, startrow, endrow) { char_u *prev_ptr, *p; int len; + hlf_T spell_hlf = HLF_COUNT; # ifdef FEAT_MBYTE if (has_mbyte) { @@ -3736,23 +3743,23 @@ win_line(wp, lnum, startrow, endrow) else p = prev_ptr; cap_col -= (prev_ptr - line); - len = spell_check(wp, p, &spell_attr, &cap_col); + len = spell_check(wp, p, &spell_hlf, &cap_col); word_end = v + len; /* In Insert mode only highlight a word that * doesn't touch the cursor. */ - if (spell_attr != 0 + if (spell_hlf != HLF_COUNT && (State & INSERT) != 0 && wp->w_cursor.lnum == lnum && wp->w_cursor.col >= (colnr_T)(prev_ptr - line) && wp->w_cursor.col < (colnr_T)word_end) { - spell_attr = 0; + spell_hlf = HLF_COUNT; spell_redraw_lnum = lnum; } - if (spell_attr == 0 && p != prev_ptr + if (spell_hlf == HLF_COUNT && p != prev_ptr && (p - nextline) + len > nextline_idx) { /* Remember that the good word continues at the @@ -3761,6 +3768,10 @@ win_line(wp, lnum, startrow, endrow) checked_col = (p - nextline) + len - nextline_idx; } + /* Turn index into actual attributes. */ + if (spell_hlf != HLF_COUNT) + spell_attr = highlight_attr[spell_hlf]; + if (cap_col > 0) { if (p != prev_ptr @@ -3889,7 +3900,7 @@ win_line(wp, lnum, startrow, endrow) * "$". */ if ( # ifdef FEAT_DIFF - diff_hlf == (enum hlf_value)0 + diff_hlf == (hlf_T)0 # ifdef LINE_ATTR && # endif @@ -3976,7 +3987,7 @@ win_line(wp, lnum, startrow, endrow) #if defined(FEAT_DIFF) || defined(LINE_ATTR) else if (( # ifdef FEAT_DIFF - diff_hlf != (enum hlf_value)0 + diff_hlf != (hlf_T)0 # ifdef LINE_ATTR || # endif @@ -6398,6 +6409,10 @@ screen_draw_rectangle(row, col, height, width, invert) int r, c; int off; + /* Can't use ScreenLines unless initialized */ + if (ScreenLines == NULL) + return; + if (invert) screen_char_attr = HL_INVERSE; for (r = row; r < row + height; ++r) @@ -6696,6 +6711,7 @@ screenalloc(clear) unsigned *new_LineOffset; char_u *new_LineWraps; static int entered = FALSE; /* avoid recursiveness */ + static int did_outofmem_msg = FALSE; /* did outofmem message */ /* * Allocation of the screen buffers is done only when the size changes and @@ -6790,7 +6806,15 @@ screenalloc(clear) || new_LineWraps == NULL || outofmem) { - do_outofmem_msg((long_u)((Rows + 1) * Columns)); /* guess the size */ + if (ScreenLines != NULL || !did_outofmem_msg) + { + /* guess the size */ + do_outofmem_msg((long_u)((Rows + 1) * Columns)); + + /* Remember we did this to avoid getting outofmem messages over + * and over again. */ + did_outofmem_msg = TRUE; + } vim_free(new_ScreenLines); new_ScreenLines = NULL; #ifdef FEAT_MBYTE @@ -6812,6 +6836,8 @@ screenalloc(clear) } else { + did_outofmem_msg = FALSE; + for (new_row = 0; new_row < Rows; ++new_row) { new_LineOffset[new_row] = new_row * Columns; @@ -6844,7 +6870,7 @@ screenalloc(clear) (void)vim_memset(new_ScreenAttrs + new_row * Columns, 0, (size_t)Columns * sizeof(sattr_T)); old_row = new_row + (screen_Rows - Rows); - if (old_row >= 0) + if (old_row >= 0 && ScreenLines != NULL) { if (screen_Columns < Columns) len = screen_Columns; diff --git a/src/search.c b/src/search.c index 2ed15df2b..f4e8f611e 100644 --- a/src/search.c +++ b/src/search.c @@ -4410,6 +4410,7 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments, int i; char_u *already = NULL; char_u *startp = NULL; + char_u *inc_opt = NULL; #ifdef RISCOS int previous_munging = __riscosify_control; #endif @@ -4449,10 +4450,10 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments, if (regmatch.regprog == NULL) goto fpip_end; } - if (*curbuf->b_p_inc != NUL || *p_inc != NUL) + inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc; + if (*inc_opt != NUL) { - incl_regmatch.regprog = vim_regcomp(*curbuf->b_p_inc == NUL - ? p_inc : curbuf->b_p_inc, p_magic ? RE_MAGIC : 0); + incl_regmatch.regprog = vim_regcomp(inc_opt, p_magic ? RE_MAGIC : 0); if (incl_regmatch.regprog == NULL) goto fpip_end; incl_regmatch.rm_ic = FALSE; /* don't ignore case in incl. pat. */ @@ -4484,10 +4485,18 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments, if (incl_regmatch.regprog != NULL && vim_regexec(&incl_regmatch, line, (colnr_T)0)) { - new_fname = file_name_in_line(incl_regmatch.endp[0], - 0, FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, - curr_fname == curbuf->b_fname - ? curbuf->b_ffname : curr_fname); + char_u *p_fname = (curr_fname == curbuf->b_fname) + ? curbuf->b_ffname : curr_fname; + + if (inc_opt != NULL && strstr((char *)inc_opt, "\\zs") != NULL) + /* Use text from '\zs' to '\ze' (or end) of 'include'. */ + new_fname = find_file_name_in_path(incl_regmatch.startp[0], + incl_regmatch.endp[0] - incl_regmatch.startp[0], + FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname); + else + /* Use text after match with 'include'. */ + new_fname = file_name_in_line(incl_regmatch.endp[0], 0, + FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname); already_searched = FALSE; if (new_fname != NULL) { diff --git a/src/spell.c b/src/spell.c index 53447afb9..6076dfc86 100644 --- a/src/spell.c +++ b/src/spell.c @@ -477,6 +477,8 @@ typedef struct suginfo_S int su_badflags; /* caps flags for bad word */ char_u su_badword[MAXWLEN]; /* bad word truncated at su_badlen */ char_u su_fbadword[MAXWLEN]; /* su_badword case-folded */ + char_u su_sal_badword[MAXWLEN]; /* su_badword soundfolded */ + slang_T *su_slang_first; /* slang_T used for su_sal_badword */ hashtab_T su_banned; /* table with banned words */ slang_T *su_sallang; /* default language for sound folding */ } suginfo_T; @@ -749,6 +751,7 @@ static void add_banned __ARGS((suginfo_T *su, char_u *word)); static int was_banned __ARGS((suginfo_T *su, char_u *word)); static void free_banned __ARGS((suginfo_T *su)); static void rescore_suggestions __ARGS((suginfo_T *su)); +static void rescore_one __ARGS((suginfo_T *su, suggest_T *stp)); static int cleanup_suggestions __ARGS((garray_T *gap, int maxscore, int keep)); static void spell_soundfold __ARGS((slang_T *slang, char_u *inword, int folded, char_u *res)); static void spell_soundfold_sofo __ARGS((slang_T *slang, char_u *inword, char_u *res)); @@ -815,8 +818,8 @@ static char *msg_compressing = N_("Compressing word tree..."); /* * Main spell-checking function. * "ptr" points to a character that could be 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. + * "*attrp" is set to the highlight index 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. * * "capcol" is used to check for a Capitalised word after the end of a @@ -831,7 +834,7 @@ static char *msg_compressing = N_("Compressing word tree..."); spell_check(wp, ptr, attrp, capcol) win_T *wp; /* current window */ char_u *ptr; - int *attrp; + hlf_T *attrp; int *capcol; /* column to check for Capital */ { matchinf_T mi; /* Most things are put in "mi" so that it can @@ -1008,17 +1011,17 @@ spell_check(wp, ptr, attrp, capcol) } if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED) - *attrp = highlight_attr[HLF_SPB]; + *attrp = HLF_SPB; else if (mi.mi_result == SP_RARE) - *attrp = highlight_attr[HLF_SPR]; + *attrp = HLF_SPR; else - *attrp = highlight_attr[HLF_SPL]; + *attrp = HLF_SPL; } if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE)) { /* Report SpellCap only when the word isn't badly spelled. */ - *attrp = highlight_attr[HLF_SPC]; + *attrp = HLF_SPC; return wrongcaplen; } @@ -1822,7 +1825,8 @@ spell_move_to(wp, dir, allwords, curline, attrp) int dir; /* FORWARD or BACKWARD */ int allwords; /* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */ int curline; - int *attrp; /* return: attributes of bad word or NULL */ + hlf_T *attrp; /* return: attributes of bad word or NULL + (only when "dir" is FORWARD) */ { linenr_T lnum; pos_T found_pos; @@ -1830,7 +1834,7 @@ spell_move_to(wp, dir, allwords, curline, attrp) char_u *line; char_u *p; char_u *endp; - int attr; + hlf_T attr; int len; int has_syntax = syntax_present(wp->w_buffer); int col; @@ -1900,13 +1904,13 @@ spell_move_to(wp, dir, allwords, curline, attrp) break; /* start of word */ - attr = 0; + attr = HLF_COUNT; len = spell_check(wp, p, &attr, &capcol); - if (attr != 0) + if (attr != HLF_COUNT) { /* We found a bad word. Check the attribute. */ - if (allwords || attr == highlight_attr[HLF_SPB]) + if (allwords || attr == HLF_SPB) { found_one = TRUE; @@ -2017,7 +2021,7 @@ spell_move_to(wp, dir, allwords, curline, attrp) /* Skip the characters at the start of the next line that were * included in a match crossing line boundaries. */ - if (attr == 0) + if (attr == HLF_COUNT) skip = p - endp; else skip = 0; @@ -5098,7 +5102,9 @@ spell_read_aff(spin, fname) ga_append(&spin->si_map, '/'); } } - else if (STRCMP(items[0], "SAL") == 0 && itemcnt == 3) + /* Accept "SAL from to" and "SAL from to # comment". */ + else if (STRCMP(items[0], "SAL") == 0 + && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#'))) { if (do_sal) { @@ -8769,7 +8775,7 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap) int banbadword; /* don't include badword in suggestions */ int need_cap; /* word should start with capital */ { - int attr = 0; + hlf_T attr = HLF_COUNT; char_u buf[MAXPATHL]; char_u *p; int do_combine = FALSE; @@ -8821,11 +8827,17 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap) } } + /* Soundfold the bad word with the default sound folding, so that we don't + * have to do this many times. */ + if (su->su_sallang != NULL) + spell_soundfold(su->su_sallang, su->su_fbadword, TRUE, + su->su_sal_badword); + /* If the word is not capitalised and spell_check() doesn't consider the * word to be bad then it might need to be capitalised. Add a suggestion * for that. */ c = PTR2CHAR(su->su_badptr); - if (!SPELL_ISUPPER(c) && attr == 0) + if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) { make_case_word(su->su_badword, buf, WF_ONECAP); add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE, @@ -9173,8 +9185,11 @@ suggest_try_special(su) su->su_fbadword[len] = NUL; make_case_word(su->su_fbadword, word, su->su_badflags); su->su_fbadword[len] = c; - add_suggestion(su, &su->su_ga, word, su->su_badlen, SCORE_DEL, - 0, TRUE, su->su_sallang); + + /* Give a soundalike score of 0, compute the score as if deleting one + * character. */ + add_suggestion(su, &su->su_ga, word, su->su_badlen, + RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang); } } @@ -9226,6 +9241,8 @@ suggest_try_change(su) slang_T *slang; int fword_ends; int lpi; + int maysplit; + int goodword_ends; /* We make a copy of the case-folded bad word, so that we can modify it * to find matches (esp. REP items). Append some more text, changing @@ -9401,10 +9418,13 @@ suggest_try_change(su) } } - /* Check NEEDCOMPOUND: can't use word without compounding. */ + /* Check NEEDCOMPOUND: can't use word without compounding. Do + * try appending another compound word below. */ if (sp->ts_complen == sp->ts_compsplit && fword_ends && (flags & WF_NEEDCOMP)) - break; + goodword_ends = FALSE; + else + goodword_ends = TRUE; if (sp->ts_complen > sp->ts_compsplit) { @@ -9508,9 +9528,15 @@ suggest_try_change(su) add_banned(su, preword + sp->ts_prewordlen); break; } - if (was_banned(su, preword + sp->ts_prewordlen) + if ((sp->ts_complen == sp->ts_compsplit + && was_banned(su, preword + sp->ts_prewordlen)) || was_banned(su, preword)) - break; + { + if (slang->sl_compprog == NULL) + break; + /* the word so far was banned but we may try compounding */ + goodword_ends = FALSE; + } newscore = 0; if ((flags & WF_REGION) @@ -9523,7 +9549,9 @@ suggest_try_change(su) captype(preword + sp->ts_prewordlen, NULL))) newscore += SCORE_ICASE; - if (fword_ends && sp->ts_fidx >= sp->ts_fidxtry) + maysplit = TRUE; + if (fword_ends && goodword_ends + && sp->ts_fidx >= sp->ts_fidxtry) { /* The badword also ends: add suggestions. Give a penalty * when changing non-word char to word char, e.g., "thes," @@ -9549,11 +9577,20 @@ suggest_try_change(su) } add_suggestion(su, &su->su_ga, preword, - sp->ts_fidx - repextra, - sp->ts_score + newscore, 0, FALSE, - lp->lp_sallang); + sp->ts_fidx - repextra, + sp->ts_score + newscore, 0, FALSE, + lp->lp_sallang); + + /* When the bad word doesn't end yet, try changing the + * next word. E.g., find suggestions for "the the" where + * the second "the" is different. It's done like a split. + */ + if (sp->ts_fidx - repextra >= su->su_badlen) + maysplit = FALSE; } - else if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends) + + if (maysplit + && (sp->ts_fidx >= sp->ts_fidxtry || fword_ends) #ifdef FEAT_MBYTE /* Don't split halfway a character. */ && (!has_mbyte || sp->ts_tcharlen == 0) @@ -9574,7 +9611,7 @@ suggest_try_change(su) * the following word is valid. */ try_compound = FALSE; - if (!fword_ends + if ((!fword_ends || !goodword_ends) && slang->sl_compprog != NULL && ((unsigned)flags >> 24) != 0 && sp->ts_twordlen - sp->ts_splitoff @@ -9618,7 +9655,7 @@ suggest_try_change(su) else sp->ts_flags &= ~TSF_DIDSPLIT; - if (!try_compound && !fword_ends) + if (!try_compound && (!fword_ends || !goodword_ends)) { /* If we're going to split need to check that the * words so far are valid for compounding. If there @@ -9656,10 +9693,12 @@ suggest_try_change(su) /* If the badword has a non-word character at this * position skip it. That means replacing the * non-word character with a space. Always skip a - * character when the word ends. */ - if ((!try_compound - && !spell_iswordp_nmw(fword + sp->ts_fidx)) + * character when the word ends. But only when the + * good word can end. */ + if (((!try_compound + && !spell_iswordp_nmw(fword + sp->ts_fidx)) || fword_ends) + && goodword_ends) { int l; @@ -10726,12 +10765,17 @@ stp_sal_score(stp, su, slang, badsound) char_u *badsound; /* sound-folded badword */ { char_u *p; + char_u *pbad; + char_u *pgood; char_u badsound2[MAXWLEN]; char_u fword[MAXWLEN]; char_u goodsound[MAXWLEN]; + char_u goodword[MAXWLEN]; + int lendiff; - if (stp->st_orglen <= su->su_badlen) - p = badsound; + lendiff = (int)(su->su_badlen - stp->st_orglen); + if (lendiff >= 0) + pbad = badsound; else { /* soundfold the bad word with more characters following */ @@ -10747,13 +10791,24 @@ stp_sal_score(stp, su, slang, badsound) mch_memmove(p, p + 1, STRLEN(p)); spell_soundfold(slang, fword, TRUE, badsound2); - p = badsound2; + pbad = badsound2; } + if (lendiff > 0) + { + /* Add part of the bad word to the good word, so that we soundfold + * what replaces the bad word. */ + STRCPY(goodword, stp->st_word); + STRNCAT(goodword, su->su_badptr + su->su_badlen - lendiff, lendiff); + pgood = goodword; + } + else + pgood = stp->st_word; + /* Sound-fold the word and compute the score for the difference. */ - spell_soundfold(slang, stp->st_word, FALSE, goodsound); + spell_soundfold(slang, pgood, FALSE, goodsound); - return soundalike_score(goodsound, p); + return soundalike_score(goodsound, pbad); } /* @@ -11081,23 +11136,24 @@ similar_chars(slang, c1, c2) * with spell_edit_score(). */ static void -add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang) +add_suggestion(su, gap, goodword, badlenarg, score, altscore, had_bonus, slang) suginfo_T *su; garray_T *gap; char_u *goodword; - int badlen; /* length of bad word used */ + int badlenarg; /* len of bad word replaced with "goodword" */ int score; int altscore; int had_bonus; /* value for st_had_bonus */ slang_T *slang; /* language for sound folding */ { - int goodlen = STRLEN(goodword); + int goodlen = STRLEN(goodword); /* len of goodword changed */ + int badlen = badlenarg; /* len of bad word changed */ suggest_T *stp; + suggest_T new_sug; int i; - char_u *p = NULL; - int c = 0; - int attr = 0; + hlf_T attr = HLF_COUNT; char_u longword[MAXWLEN + 1]; + char_u *pgood, *pbad; /* Check that the word really is valid. Esp. for banned words and for * split words, such as "the the". Need to append what follows to check @@ -11105,36 +11161,34 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang) STRCPY(longword, goodword); vim_strncpy(longword + goodlen, su->su_badptr + badlen, MAXWLEN - goodlen); (void)spell_check(curwin, longword, &attr, NULL); - if (attr != 0) + if (attr != HLF_COUNT) return; - /* If past "su_badlen" and the rest is identical stop at "su_badlen". - * Remove the common part from "goodword". */ - i = badlen - su->su_badlen; - if (i > 0) + /* Minimize "badlen" for consistency. Avoids that changing "the the" to + * "thee the" is added next to changing the first "the" the "thee". */ + pgood = goodword + STRLEN(goodword); + pbad = su->su_badptr + badlen; + while (pgood > goodword && pbad > su->su_badptr) { - /* This assumes there was no case folding or it didn't change the - * length... */ - p = goodword + goodlen - i; - if (p > goodword && STRNICMP(su->su_badptr + su->su_badlen, p, i) == 0) + mb_ptr_back(goodword, pgood); + mb_ptr_back(su->su_badptr, pbad); +#ifdef FEAT_MBYTE + if (has_mbyte) { - badlen = su->su_badlen; - c = *p; - *p = NUL; + if (mb_ptr2char(pgood) != mb_ptr2char(pbad)) + break; } else - p = NULL; - } - else if (i < 0) - { - /* When replacing part of the word check that we actually change - * something. For "the the" a suggestion can be replacing the first - * "the" with itself, since "the" wasn't banned. */ - if (badlen == (int)goodlen - && STRNCMP(su->su_badword, goodword, badlen) == 0) - return; +#endif + if (*pgood != *pbad) + break; + badlen = pbad - su->su_badptr; + goodlen = pgood - goodword; } - + if (badlen == 0 && goodlen == 0) + /* goodword doesn't change anything; may happen for "the the" changing + * the first "the" to itself. */ + return; if (score <= su->su_maxscore) { @@ -11143,18 +11197,44 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang) * "thes" -> "these". */ stp = &SUG(*gap, 0); for (i = gap->ga_len - 1; i >= 0; --i) - if (STRCMP(stp[i].st_word, goodword) == 0 + if (STRLEN(stp[i].st_word) == goodlen + && STRNCMP(stp[i].st_word, goodword, goodlen) == 0 && stp[i].st_orglen == badlen) { - /* Found it. Remember the lowest score. */ - if (stp[i].st_score > score) - { - stp[i].st_score = score; - stp[i].st_altscore = altscore; - stp[i].st_had_bonus = had_bonus; - } + /* + * Found it. Remember the lowest score. + */ if (stp[i].st_slang == NULL) stp[i].st_slang = slang; + + new_sug.st_score = score; + new_sug.st_altscore = altscore; + new_sug.st_had_bonus = had_bonus; + + if (stp[i].st_had_bonus != had_bonus) + { + /* Only one of the two had the soundalike score computed. + * Need to do that for the other one now, otherwise the + * scores can't be compared. This happens because + * suggest_try_change() doesn't compute the soundalike + * word to keep it fast. */ + if (had_bonus) + rescore_one(su, &stp[i]); + else + { + new_sug.st_word = goodword; + new_sug.st_slang = stp[i].st_slang; + new_sug.st_orglen = badlen; + rescore_one(su, &new_sug); + } + } + + if (stp[i].st_score > new_sug.st_score) + { + stp[i].st_score = new_sug.st_score; + stp[i].st_altscore = new_sug.st_altscore; + stp[i].st_had_bonus = new_sug.st_had_bonus; + } break; } @@ -11162,7 +11242,7 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang) { /* Add a suggestion. */ stp = &SUG(*gap, gap->ga_len); - stp->st_word = vim_strsave(goodword); + stp->st_word = vim_strnsave(goodword, goodlen); if (stp->st_word != NULL) { stp->st_score = score; @@ -11180,9 +11260,6 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang) } } } - - if (p != NULL) - *p = c; /* restore "goodword" */ } /* @@ -11244,62 +11321,47 @@ free_banned(su) } /* - * Recompute the score if sound-folding is possible. This is slow, - * thus only done for the final results. + * Recompute the score for all suggestions if sound-folding is possible. This + * is slow, thus only done for the final results. */ static void rescore_suggestions(su) suginfo_T *su; { - langp_T *lp; - suggest_T *stp; - char_u sal_badword[MAXWLEN]; - char_u sal_badword2[MAXWLEN]; int i; - int lpi; - slang_T *slang_first = NULL; - slang_T *slang; - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); - if (lp->lp_slang->sl_sal.ga_len > 0) - { - /* soundfold the bad word */ - slang_first = lp->lp_slang; - spell_soundfold(slang_first, su->su_fbadword, TRUE, sal_badword); - break; - } - } + if (su->su_sallang != NULL) + for (i = 0; i < su->su_ga.ga_len; ++i) + rescore_one(su, &SUG(su->su_ga, i)); +} + +/* + * Recompute the score for one suggestion if sound-folding is possible. + */ + static void +rescore_one(su, stp) + suginfo_T *su; + suggest_T *stp; +{ + slang_T *slang = stp->st_slang; + char_u sal_badword[MAXWLEN]; - if (slang_first != NULL) + /* Only rescore suggestions that have no sal score yet and do have a + * language. */ + if (slang != NULL && slang->sl_sal.ga_len > 0 && !stp->st_had_bonus) { - for (i = 0; i < su->su_ga.ga_len; ++i) + if (slang == su->su_sallang) + stp->st_altscore = stp_sal_score(stp, su, + slang, su->su_sal_badword); + else { - /* Only rescore suggestions that have no sal score yet and do have - * a language. */ - stp = &SUG(su->su_ga, i); - if (!stp->st_had_bonus && stp->st_slang != NULL) - { - slang = stp->st_slang; - if (slang->sl_sal.ga_len > 0) - { - if (slang == slang_first) - stp->st_altscore = stp_sal_score(stp, su, - slang, sal_badword); - else - { - spell_soundfold(slang, su->su_fbadword, - TRUE, sal_badword2); - stp->st_altscore = stp_sal_score(stp, su, - slang, sal_badword2); - } - if (stp->st_altscore == SCORE_MAXMAX) - stp->st_altscore = SCORE_BIG; - stp->st_score = RESCORE(stp->st_score, stp->st_altscore); - } - } + spell_soundfold(slang, su->su_fbadword, TRUE, sal_badword); + stp->st_altscore = stp_sal_score(stp, su, slang, sal_badword); } + if (stp->st_altscore == SCORE_MAXMAX) + stp->st_altscore = SCORE_BIG; + stp->st_score = RESCORE(stp->st_score, stp->st_altscore); + stp->st_had_bonus = TRUE; } } diff --git a/src/testdir/test58.ok b/src/testdir/test58.ok index 736e9929c..75caa7e66 100644 --- a/src/testdir/test58.ok +++ b/src/testdir/test58.ok @@ -30,7 +30,7 @@ ok Ok ['OK', 'Uk', 'Put'] test -['test', 'Test', 'testn'] +['Test', 'testn', 'testen'] déôl ['deol', 'déôr', 'test'] end @@ -87,7 +87,7 @@ end the ['put', 'uk', 'test'] test -['test', 'Test', 'testn'] +['Test', 'testn', 'testen'] déôl ['deol', 'déôr', 'test'] @@ -99,13 +99,13 @@ mï bad ['foo', 'mï'] bar -['foobar', 'foo', 'mï'] +['barfoo', 'foobar', 'foo'] la ['mï', 'foo'] foomï ['foo mï', 'foo', 'foofoo'] barmï -['barfoo', 'barbar', 'mï'] +['barfoo', 'mï', 'barbar'] mïfoo ['mï foo', 'foo', 'foofoo'] mïbar diff --git a/src/testdir/test59.ok b/src/testdir/test59.ok index 8f476677e..9c49be4cb 100644 --- a/src/testdir/test59.ok +++ b/src/testdir/test59.ok @@ -30,7 +30,7 @@ ok Ok ['OK', 'Uk', 'Put'] test -['test', 'Test', 'testn'] +['Test', 'testn', 'testen'] déôl ['deol', 'déôr', 'test'] end @@ -87,7 +87,7 @@ end the ['put', 'uk', 'test'] test -['test', 'Test', 'testn'] +['Test', 'testn', 'testen'] déôl ['deol', 'déôr', 'test'] @@ -99,13 +99,13 @@ mï bad ['foo', 'mï'] bar -['foobar', 'foo', 'mï'] +['barfoo', 'foobar', 'foo'] la ['mï', 'foo'] foomï ['foo mï', 'foo', 'foofoo'] barmï -['barfoo', 'barbar', 'mï'] +['barfoo', 'mï', 'barbar'] mïfoo ['mï foo', 'foo', 'foofoo'] mïbar @@ -1142,6 +1142,10 @@ clip_copy_modeless_selection(both) int row2 = clip_star.end.lnum; int col2 = clip_star.end.col; + /* Can't use ScreenLines unless initialized */ + if (ScreenLines == NULL) + return; + /* * Make sure row1 <= row2, and if row1 == row2 that col1 <= col2. */ @@ -1312,7 +1316,7 @@ clip_get_word_boundaries(cb, row, col) int mboff; #endif - if (row >= screen_Rows || col >= screen_Columns) + if (row >= screen_Rows || col >= screen_Columns || ScreenLines == NULL) return; p = ScreenLines + LineOffset[row]; @@ -1367,7 +1371,7 @@ clip_get_line_end(row) { int i; - if (row >= screen_Rows) + if (row >= screen_Rows || ScreenLines == NULL) return 0; for (i = screen_Columns; i > 0; i--) if (ScreenLines[LineOffset[row] + i - 1] != ' ') @@ -2432,7 +2436,8 @@ retnomove: #ifdef FEAT_FOLDING /* Remember the character under the mouse, it might be a '-' or '+' in the * fold column. */ - if (row >= 0 && row < Rows && col >= 0 && col <= Columns) + if (row >= 0 && row < Rows && col >= 0 && col <= Columns + && ScreenLines != NULL) mouse_char = ScreenLines[LineOffset[row] + col]; else mouse_char = ' '; diff --git a/src/version.h b/src/version.h index cf19c79dd..70e2f4d3e 100644 --- a/src/version.h +++ b/src/version.h @@ -36,5 +36,5 @@ #define VIM_VERSION_NODOT "vim70aa" #define VIM_VERSION_SHORT "7.0aa" #define VIM_VERSION_MEDIUM "7.0aa ALPHA" -#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Sep 25)" -#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Sep 25, compiled " +#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Sep 29)" +#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Sep 29, compiled " @@ -1116,7 +1116,7 @@ typedef enum auto_event EVENT_T; * When making changes, also update HL_FLAGS below! And update the default * value of 'highlight' in option.c. */ -enum hlf_value +typedef enum { HLF_8 = 0 /* Meta & special keys listed with ":map", text that is displayed different from what it is */ @@ -1151,7 +1151,7 @@ enum hlf_value , HLF_SPR /* SpellRare */ , HLF_SPL /* SpellLocal */ , HLF_COUNT /* MUST be the last one */ -}; +} hlf_T; /* the HL_FLAGS must be in the same order as the HLF_ enums! */ #define HL_FLAGS {'8', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \ |