diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 4f5dd6aca9..b51d88cb66 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.2. Last change: 2008 Nov 02 +*eval.txt* For Vim version 7.2. Last change: 2008 Nov 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1706,7 +1706,7 @@ executable( {expr}) Number 1 if executable {expr} exists exists( {expr}) Number TRUE if {expr} exists extend({expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} -expand( {expr}) String expand special keywords in {expr} +expand( {expr} [, {flag}]) String expand special keywords in {expr} feedkeys( {string} [, {mode}]) Number add key sequence to typeahead buffer filereadable( {file}) Number TRUE if {file} is a readable file filewritable( {file}) Number TRUE if {file} is a writable file @@ -1758,8 +1758,9 @@ gettabwinvar( {tabnr}, {winnr}, {name}) getwinposx() Number X coord in pixels of GUI Vim window getwinposy() Number Y coord in pixels of GUI Vim window getwinvar( {nr}, {varname}) any variable {varname} in window {nr} -glob( {expr}) String expand file wildcards in {expr} -globpath( {path}, {expr}) String do glob({expr}) for all dirs in {path} +glob( {expr} [, {flag}]) String expand file wildcards in {expr} +globpath( {path}, {expr} [, {flag}]) + String do glob({expr}) for all dirs in {path} has( {feature}) Number TRUE if feature {feature} supported has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} haslocaldir() Number TRUE if current window executed |:lcd| @@ -3286,14 +3287,16 @@ getwinvar({winnr}, {varname}) *getwinvar()* :let list_is_on = getwinvar(2, '&list') :echo "myvar = " . getwinvar(1, 'myvar') < - *glob()* -glob({expr}) Expand the file wildcards in {expr}. See |wildcards| for the +glob({expr} [, {flag}]) *glob()* + Expand the file wildcards in {expr}. See |wildcards| for the use of special characters. The result is a String. When there are several matches, they are separated by characters. - The 'wildignore' option applies: Names matching one of the - patterns in 'wildignore' will be skipped. + Unless the optional {flag} argument is given and is non-zero, + the 'suffixes' and 'wildignore' options apply: Names matching + one of the patterns in 'wildignore' will be skipped and + 'suffixes' affect the ordering of matches. If the expansion fails, the result is an empty string. A name for a non-existing file is not included. @@ -3307,20 +3310,22 @@ glob({expr}) Expand the file wildcards in {expr}. See |wildcards| for the See |expand()| for expanding special Vim variables. See |system()| for getting the raw output of an external command. -globpath({path}, {expr}) *globpath()* +globpath({path}, {expr} [, {flag}]) *globpath()* Perform glob() on all directories in {path} and concatenate the results. Example: > :echo globpath(&rtp, "syntax/c.vim") < {path} is a comma-separated list of directory names. Each directory name is prepended to {expr} and expanded like with - glob(). A path separator is inserted when needed. + |glob()|. A path separator is inserted when needed. To add a comma inside a directory name escape it with a backslash. Note that on MS-Windows a directory may have a trailing backslash, remove it if you put a comma after it. If the expansion fails for one of the directories, there is no error message. - The 'wildignore' option applies: Names matching one of the - patterns in 'wildignore' will be skipped. + Unless the optional {flag} argument is given and is non-zero, + the 'suffixes' and 'wildignore' options apply: Names matching + one of the patterns in 'wildignore' will be skipped and + 'suffixes' affect the ordering of matches. The "**" item can be used to search in a directory tree. For example, to find all "README.txt" files in the directories @@ -5343,10 +5348,12 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()* "fg" foreground color (GUI: color name used to set the color, cterm: color number as a string, term: empty string) - "bg" background color (like "fg") + "bg" background color (as with "fg") + "sp" special color (as with "fg") |highlight-guisp| "fg#" like "fg", but for the GUI and the GUI is running the name in "#RRGGBB" form "bg#" like "fg#" for "bg" + "sp#" like "fg#" for "sp" "bold" "1" if bold "italic" "1" if italic "reverse" "1" if reverse @@ -5836,7 +5843,8 @@ mouse_netterm Compiled with support for netterm mouse. mouse_pterm Compiled with support for qnx pterm mouse. mouse_sysmouse Compiled with support for sysmouse (*BSD console mouse) mouse_xterm Compiled with support for xterm mouse. -multi_byte Compiled with support for editing Korean et al. +multi_byte Compiled with support for 'encoding' +multi_byte_encoding 'encoding' is set to a multi-byte encoding. multi_byte_ime Compiled with support for IME input method. multi_lang Compiled with support for multiple languages. mzscheme Compiled with MzScheme interface |mzscheme|. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 7b046d5226..9fb242a452 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.2. Last change: 2008 Aug 06 +*options.txt* For Vim version 7.2. Last change: 2008 Nov 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -7595,7 +7595,9 @@ A jump table for the options with a short description can be found at |Q_op|. {not available when compiled without the |+wildignore| feature} A list of file patterns. A file that matches with one of these - patterns is ignored when completing file or directory names. + patterns is ignored when completing file or directory names, and + influences the result of |expand()|, |glob()| and |globpath()| unless + a flag is passed to disable this. The pattern is used like with |:autocmd|, see |autocmd-patterns|. Also see 'suffixes'. Example: > diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index d1e478e9a5..93b3ad8757 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -1,4 +1,4 @@ -*spell.txt* For Vim version 7.2. Last change: 2008 Jun 21 +*spell.txt* For Vim version 7.2. Last change: 2008 Nov 30 VIM REFERENCE MANUAL by Bram Moolenaar @@ -831,8 +831,11 @@ Comment lines in the .aff file start with a '#': # comment line ~ -With some items it's also possible to put a comment after it, but this isn't -supported in general. +Items with a fixed number of arguments can be followed by a comment. But only +if none of the arguments can contain white space. The comment must start with +a "#" character. Example: + + KEEPCASE = # fix case for words with this flag ~ ENCODING *spell-SET* @@ -965,6 +968,9 @@ common items and two-character flags for uncommon items. Note: When using utf-8 only characters up to 65000 may be used for flags. +Note: even when using "num" or "long" the number of flags available to +compounding and prefixes is limited to about 250. + AFFIXES *spell-PFX* *spell-SFX* @@ -1178,6 +1184,9 @@ word as good. The flag also applies to the word with affixes, thus this can be used to mark a whole bunch of related words as bad. + *spell-FORBIDDENWORD* +FORBIDDENWORD can be used just like BAD. For compatibility with Hunspell. + *spell-NEEDAFFIX* The NEEDAFFIX flag is used to require that a word is used with an affix. The word itself is not a good word (unless there is an empty affix). Example: @@ -1268,6 +1277,10 @@ compound word. The word itself is not a good word. Example: NEEDCOMPOUND & ~ + *spell-ONLYINCOMPOUND* +The ONLYINCOMPOUND does exactly the same as NEEDCOMPOUND. Supported for +compatiblity with Hunspell. + *spell-COMPOUNDMIN* The minimal character length of a word used for compounding is specified with COMPOUNDMIN. Example: @@ -1328,6 +1341,20 @@ compound. This means it counts for two words when checking the compounding rules. Can also be used for an affix to count the affix as a compounding word. + *spell-CHECKCOMPOUNDPATTERN* +CHECKCOMPOUNDPATTERN is used to define patterns that, when matching at the +position where two words are compounded together forbids the compound. +For example: + CHECKCOMPOUNDPATTERN o e ~ + +This forbids compounding if the first word ends in "o" and the second word +starts with "e". + +The arguments must be plain text, no patterns are actually supported, despite +the item name. Case is always ignored. + +The Hunspell feature to use three arguments and flags is not supported. + *spell-SYLLABLE* The SYLLABLE item defines characters or character sequences that are used to count the number of syllables in a word. Example: @@ -1496,6 +1523,10 @@ ignored, not supported or defined in another way. ACCENT (Hunspell) *spell-ACCENT* Use MAP instead. |spell-MAP| +BREAK (Hunspell) *spell-BREAK* + Define break points. Unclear how it works exactly. + Not supported. + CHECKCOMPOUNDCASE (Hunspell) *spell-CHECKCOMPOUNDCASE* Disallow uppercase letters at compound word boundaries. Not supported. @@ -1512,9 +1543,6 @@ CHECKCOMPOUNDTRIPLE (Hunspell) *spell-CHECKCOMPOUNDTRIPLE* Forbid three identical characters when compounding. Not supported. -CHECKCOMPOUNDPATTERN (Hunspell) *spell-CHECKCOMPOUNDPATTERN* - Forbid compounding when patterns match. Not supported. - COMPLEXPREFIXES (Hunspell) *spell-COMPLEXPREFIXES* Enables using two prefixes. Not supported. @@ -1536,13 +1564,18 @@ COMPOUNDEND (Hunspell) *spell-COMPOUNDEND* COMPOUNDMIDDLE (Hunspell) *spell-COMPOUNDMIDDLE* Use COMPOUNDRULE instead. |spell-COMPOUNDRULE| +COMPOUNDRULES (Hunspell) *spell-COMPOUNDRULES* + Number of COMPOUNDRULE lines following. Ignored, but the + argument must be a number. + COMPOUNDSYLLABLE (Hunspell) *spell-COMPOUNDSYLLABLE* Use SYLLABLE and COMPOUNDSYLMAX instead. |spell-SYLLABLE| |spell-COMPOUNDSYLMAX| -FORBIDDENWORD (Hunspell) *spell-FORBIDDENWORD* - Use BAD instead. |spell-BAD| - +KEY (Hunspell) *spell-KEY* + Define characters that are close together on the keyboard. + Used to give better suggestions. Not supported. + LANG (Hunspell) *spell-LANG* This specifies language-specific behavior. This actually moves part of the language knowledge into the program, @@ -1553,10 +1586,7 @@ LEMMA_PRESENT (Hunspell) *spell-LEMMA_PRESENT* Only needed for morphological analysis. MAXNGRAMSUGS (Hunspell) *spell-MAXNGRAMSUGS* - Not supported. - -ONLYINCOMPOUND (Hunspell) *spell-ONLYINCOMPOUND* - Use NEEDCOMPOUND instead. |spell-NEEDCOMPOUND| + Set number of n-gram suggestions. Not supported. PSEUDOROOT (Hunspell) *spell-PSEUDOROOT* Use NEEDAFFIX instead. |spell-NEEDAFFIX| diff --git a/src/buffer.c b/src/buffer.c index 12bc225f87..589a108112 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5128,7 +5128,7 @@ buf_spname(buf) { if (buf->b_sfname != NULL) return (char *)buf->b_sfname; - return "[Scratch]"; + return _("[Scratch]"); } #endif if (buf->b_fname == NULL) diff --git a/src/diff.c b/src/diff.c index 8bf0ed81b1..33dd483443 100644 --- a/src/diff.c +++ b/src/diff.c @@ -73,6 +73,8 @@ diff_buf_delete(buf) { tp->tp_diffbuf[i] = NULL; tp->tp_diff_invalid = TRUE; + if (tp == curtab) + diff_redraw(TRUE); } } } @@ -102,6 +104,7 @@ diff_buf_adjust(win) { curtab->tp_diffbuf[i] = NULL; curtab->tp_diff_invalid = TRUE; + diff_redraw(TRUE); } } } @@ -131,6 +134,7 @@ diff_buf_add(buf) { curtab->tp_diffbuf[i] = buf; curtab->tp_diff_invalid = TRUE; + diff_redraw(TRUE); return; } @@ -661,6 +665,7 @@ ex_diffupdate(eap) char_u *tmp_diff; FILE *fd; int ok; + int io_error = FALSE; /* Delete all diffblocks. */ diff_clear(curtab); @@ -697,18 +702,26 @@ ex_diffupdate(eap) { ok = FALSE; fd = mch_fopen((char *)tmp_orig, "w"); - if (fd != NULL) + if (fd == NULL) + io_error = TRUE; + else { - fwrite("line1\n", (size_t)6, (size_t)1, fd); + if (fwrite("line1\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; fclose(fd); fd = mch_fopen((char *)tmp_new, "w"); - if (fd != NULL) + if (fd == NULL) + io_error = TRUE; + else { - fwrite("line2\n", (size_t)6, (size_t)1, fd); + if (fwrite("line2\n", (size_t)6, (size_t)1, fd) != 1) + io_error = TRUE; fclose(fd); diff_file(tmp_orig, tmp_new, tmp_diff); fd = mch_fopen((char *)tmp_diff, "r"); - if (fd != NULL) + if (fd == NULL) + io_error = TRUE; + else { char_u linebuf[LBUFLEN]; @@ -761,6 +774,8 @@ ex_diffupdate(eap) } if (!ok) { + if (io_error) + EMSG(_("E810: Cannot read or write temp files")); EMSG(_("E97: Cannot create diffs")); diff_a_works = MAYBE; #if defined(MSWIN) || defined(MSDOS) @@ -925,10 +940,10 @@ ex_diffpatch(eap) { # ifdef TEMPDIRNAMES if (vim_tempdir != NULL) - mch_chdir((char *)vim_tempdir); + ignored = mch_chdir((char *)vim_tempdir); else # endif - mch_chdir("/tmp"); + ignored = mch_chdir("/tmp"); shorten_fnames(TRUE); } #endif diff --git a/src/eval.c b/src/eval.c index 56249df24a..5c2c966026 100644 --- a/src/eval.c +++ b/src/eval.c @@ -32,6 +32,9 @@ #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ +#define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not + be freed. */ + /* * In a hashtab item "hi_key" points to "di_key" in a dictitem. * This avoids adding a pointer to the hashtab item. @@ -789,6 +792,8 @@ static void func_free __ARGS((ufunc_T *fp)); static void func_unref __ARGS((char_u *name)); static void func_ref __ARGS((char_u *name)); static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict)); +static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ; +static void free_funccal __ARGS((funccall_T *fc, int free_val)); static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)); static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp)); static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off)); @@ -923,6 +928,10 @@ func_level(cookie) /* pointer to funccal for currently active function */ funccall_T *current_funccal = NULL; +/* pointer to list of previously used funccal, still around because some + * item in it is still being used. */ +funccall_T *previous_funccal = NULL; + /* * Return TRUE when a function was ended by a ":return" command. */ @@ -6490,7 +6499,7 @@ garbage_collect() buf_T *buf; win_T *wp; int i; - funccall_T *fc; + funccall_T *fc, **pfc; int did_free = FALSE; #ifdef FEAT_WINDOWS tabpage_T *tp; @@ -6574,6 +6583,20 @@ garbage_collect() else ll = ll->lv_used_next; + /* check if any funccal can be freed now */ + for (pfc = &previous_funccal; *pfc != NULL; ) + { + if (can_free_funccal(*pfc, copyID)) + { + fc = *pfc; + *pfc = fc->caller; + free_funccal(fc, TRUE); + did_free = TRUE; + } + else + pfc = &(*pfc)->caller; + } + return did_free; } @@ -7564,8 +7587,8 @@ static struct fst {"getwinposx", 0, 0, f_getwinposx}, {"getwinposy", 0, 0, f_getwinposy}, {"getwinvar", 2, 2, f_getwinvar}, - {"glob", 1, 1, f_glob}, - {"globpath", 2, 2, f_globpath}, + {"glob", 1, 2, f_glob}, + {"globpath", 2, 3, f_globpath}, {"has", 1, 1, f_has}, {"has_key", 2, 2, f_has_key}, {"haslocaldir", 0, 0, f_haslocaldir}, @@ -9557,7 +9580,7 @@ f_expand(argvars, rettv) else { /* When the optional second argument is non-zero, don't remove matches - * for 'suffixes' and 'wildignore' */ + * for 'wildignore' and don't put matches for 'suffixes' at the end. */ if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number_chk(&argvars[1], &error)) flags |= WILD_KEEP_ALL; @@ -10339,7 +10362,8 @@ f_function(argvars, rettv) s = get_tv_string(&argvars[0]); if (s == NULL || *s == NUL || VIM_ISDIGIT(*s)) EMSG2(_(e_invarg2), s); - else if (!function_exists(s)) + /* Don't check an autoload name for existence here. */ + else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s)) EMSG2(_("E700: Unknown function: %s"), s); else { @@ -10641,7 +10665,7 @@ f_getchar(argvars, rettv) # ifdef FEAT_WINDOWS win_T *wp; # endif - int n = 1; + int winnr = 1; if (row >= 0 && col >= 0) { @@ -10651,9 +10675,9 @@ f_getchar(argvars, rettv) (void)mouse_comp_pos(win, &row, &col, &lnum); # ifdef FEAT_WINDOWS for (wp = firstwin; wp != win; wp = wp->w_next) - ++n; + ++winnr; # endif - vimvars[VV_MOUSE_WIN].vv_nr = n; + vimvars[VV_MOUSE_WIN].vv_nr = winnr; vimvars[VV_MOUSE_LNUM].vv_nr = lnum; vimvars[VV_MOUSE_COL].vv_nr = col + 1; } @@ -11323,13 +11347,25 @@ f_glob(argvars, rettv) typval_T *argvars; typval_T *rettv; { + int flags = WILD_SILENT|WILD_USE_NL; expand_T xpc; + int error = FALSE; - ExpandInit(&xpc); - xpc.xp_context = EXPAND_FILES; + /* When the optional second argument is non-zero, don't remove matches + * for 'wildignore' and don't put matches for 'suffixes' at the end. */ + if (argvars[1].v_type != VAR_UNKNOWN + && get_tv_number_chk(&argvars[1], &error)) + flags |= WILD_KEEP_ALL; rettv->v_type = VAR_STRING; - rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), - NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL); + if (!error) + { + ExpandInit(&xpc); + xpc.xp_context = EXPAND_FILES; + rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), + NULL, flags, WILD_ALL); + } + else + rettv->vval.v_string = NULL; } /* @@ -11340,14 +11376,22 @@ f_globpath(argvars, rettv) typval_T *argvars; typval_T *rettv; { + int flags = 0; char_u buf1[NUMBUFLEN]; char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); + int error = FALSE; + /* When the optional second argument is non-zero, don't remove matches + * for 'wildignore' and don't put matches for 'suffixes' at the end. */ + if (argvars[2].v_type != VAR_UNKNOWN + && get_tv_number_chk(&argvars[2], &error)) + flags |= WILD_KEEP_ALL; rettv->v_type = VAR_STRING; - if (file == NULL) + if (file == NULL || error) rettv->vval.v_string = NULL; else - rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file); + rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file, + flags); } /* @@ -11833,6 +11877,10 @@ f_has(argvars, rettv) n = has_patch(atoi((char *)name + 5)); else if (STRICMP(name, "vim_starting") == 0) n = (starting != 0); +#ifdef FEAT_MBYTE + else if (STRICMP(name, "multi_byte_encoding") == 0) + n = has_mbyte; +#endif #if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32) else if (STRICMP(name, "balloon_multiline") == 0) n = multiline_balloon_available(); @@ -16648,8 +16696,11 @@ f_synIDattr(argvars, rettv) p = highlight_has_attr(id, HL_INVERSE, modec); break; - case 's': /* standout */ - p = highlight_has_attr(id, HL_STANDOUT, modec); + case 's': + if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */ + p = highlight_color(id, what, modec); + else /* standout */ + p = highlight_has_attr(id, HL_STANDOUT, modec); break; case 'u': @@ -18954,7 +19005,7 @@ init_var_dict(dict, dict_var) dictitem_T *dict_var; { hash_init(&dict->dv_hashtab); - dict->dv_refcount = 99999; + dict->dv_refcount = DO_NOT_FREE_CNT; dict_var->di_tv.vval.v_dict = dict; dict_var->di_tv.v_type = VAR_DICT; dict_var->di_tv.v_lock = VAR_FIXED; @@ -19291,6 +19342,8 @@ tv_check_lock(lock, name) * Copy the values from typval_T "from" to typval_T "to". * When needed allocates string or increases reference count. * Does not make a copy of a list or dict but copies the reference! + * It is OK for "from" and "to" to point to the same item. This is used to + * make a copy later. */ static void copy_tv(from, to) @@ -21103,7 +21156,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) char_u *save_sourcing_name; linenr_T save_sourcing_lnum; scid_T save_current_SID; - funccall_T fc; + funccall_T *fc; int save_did_emsg; static int depth = 0; dictitem_T *v; @@ -21129,36 +21182,37 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) line_breakcheck(); /* check for CTRL-C hit */ - fc.caller = current_funccal; - current_funccal = &fc; - fc.func = fp; - fc.rettv = rettv; + fc = (funccall_T *)alloc(sizeof(funccall_T)); + fc->caller = current_funccal; + current_funccal = fc; + fc->func = fp; + fc->rettv = rettv; rettv->vval.v_number = 0; - fc.linenr = 0; - fc.returned = FALSE; - fc.level = ex_nesting_level; + fc->linenr = 0; + fc->returned = FALSE; + fc->level = ex_nesting_level; /* Check if this function has a breakpoint. */ - fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); - fc.dbg_tick = debug_tick; + fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); + fc->dbg_tick = debug_tick; /* - * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables + * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free * each argument variable and saves a lot of time. */ /* * Init l: variables. */ - init_var_dict(&fc.l_vars, &fc.l_vars_var); + init_var_dict(&fc->l_vars, &fc->l_vars_var); if (selfdict != NULL) { /* Set l:self to "selfdict". Use "name" to avoid a warning from * some compiler that checks the destination size. */ - v = &fc.fixvar[fixvar_idx++].var; + v = &fc->fixvar[fixvar_idx++].var; name = v->di_key; STRCPY(name, "self"); v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX; - hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v)); + hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v)); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = 0; v->di_tv.vval.v_dict = selfdict; @@ -21170,31 +21224,31 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) * Set a:0 to "argcount". * Set a:000 to a list with room for the "..." arguments. */ - init_var_dict(&fc.l_avars, &fc.l_avars_var); - add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0", + init_var_dict(&fc->l_avars, &fc->l_avars_var); + add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", (varnumber_T)(argcount - fp->uf_args.ga_len)); /* Use "name" to avoid a warning from some compiler that checks the * destination size. */ - v = &fc.fixvar[fixvar_idx++].var; + v = &fc->fixvar[fixvar_idx++].var; name = v->di_key; STRCPY(name, "000"); v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v)); + hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; - v->di_tv.vval.v_list = &fc.l_varlist; - vim_memset(&fc.l_varlist, 0, sizeof(list_T)); - fc.l_varlist.lv_refcount = 99999; - fc.l_varlist.lv_lock = VAR_FIXED; + v->di_tv.vval.v_list = &fc->l_varlist; + vim_memset(&fc->l_varlist, 0, sizeof(list_T)); + fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT; + fc->l_varlist.lv_lock = VAR_FIXED; /* * Set a:firstline to "firstline" and a:lastline to "lastline". * Set a:name to named arguments. * Set a:N to the "..." arguments. */ - add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline", + add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", (varnumber_T)firstline); - add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline", + add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", (varnumber_T)lastline); for (i = 0; i < argcount; ++i) { @@ -21210,7 +21264,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) } if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) { - v = &fc.fixvar[fixvar_idx++].var; + v = &fc->fixvar[fixvar_idx++].var; v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } else @@ -21222,7 +21276,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) v->di_flags = DI_FLAGS_RO; } STRCPY(v->di_key, name); - hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v)); + hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); /* Note: the values are copied directly to avoid alloc/free. * "argvars" must have VAR_FIXED for v_lock. */ @@ -21231,9 +21285,9 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) if (ai >= 0 && ai < MAX_FUNC_ARGS) { - list_append(&fc.l_varlist, &fc.l_listitems[ai]); - fc.l_listitems[ai].li_tv = argvars[i]; - fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED; + list_append(&fc->l_varlist, &fc->l_listitems[ai]); + fc->l_listitems[ai].li_tv = argvars[i]; + fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED; } } @@ -21298,7 +21352,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) func_do_profile(fp); if (fp->uf_profiling - || (fc.caller != NULL && fc.caller->func->uf_profiling)) + || (fc->caller != NULL && fc->caller->func->uf_profiling)) { ++fp->uf_tm_count; profile_start(&call_start); @@ -21314,7 +21368,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) did_emsg = FALSE; /* call do_cmdline() to execute the lines */ - do_cmdline(NULL, get_func_line, (void *)&fc, + do_cmdline(NULL, get_func_line, (void *)fc, DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); --RedrawingDisabled; @@ -21329,16 +21383,16 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) #ifdef FEAT_PROFILE if (do_profiling == PROF_YES && (fp->uf_profiling - || (fc.caller != NULL && fc.caller->func->uf_profiling))) + || (fc->caller != NULL && fc->caller->func->uf_profiling))) { profile_end(&call_start); profile_sub_wait(&wait_start, &call_start); profile_add(&fp->uf_tm_total, &call_start); profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children); - if (fc.caller != NULL && fc.caller->func->uf_profiling) + if (fc->caller != NULL && fc->caller->func->uf_profiling) { - profile_add(&fc.caller->func->uf_tm_children, &call_start); - profile_add(&fc.caller->func->uf_tml_children, &call_start); + profile_add(&fc->caller->func->uf_tm_children, &call_start); + profile_add(&fc->caller->func->uf_tml_children, &call_start); } } #endif @@ -21351,9 +21405,9 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) if (aborting()) smsg((char_u *)_("%s aborted"), sourcing_name); - else if (fc.rettv->v_type == VAR_NUMBER) + else if (fc->rettv->v_type == VAR_NUMBER) smsg((char_u *)_("%s returning #%ld"), sourcing_name, - (long)fc.rettv->vval.v_number); + (long)fc->rettv->vval.v_number); else { char_u buf[MSG_BUF_LEN]; @@ -21364,7 +21418,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) /* The value may be very long. Skip the middle part, so that we * have some idea how it starts and ends. smsg() would always * truncate it at the end. */ - s = tv2string(fc.rettv, &tofree, numbuf2, 0); + s = tv2string(fc->rettv, &tofree, numbuf2, 0); if (s != NULL) { trunc_string(s, buf, MSG_BUF_CLEN); @@ -21400,14 +21454,84 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict) } did_emsg |= save_did_emsg; - current_funccal = fc.caller; - - /* The a: variables typevals were not allocated, only free the allocated - * variables. */ - vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE); - - vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */ + current_funccal = fc->caller; --depth; + + /* if the a:000 list and the a: dict are not referenced we can free the + * funccall_T and what's in it. */ + if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT + && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT + && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) + { + free_funccal(fc, FALSE); + } + else + { + hashitem_T *hi; + listitem_T *li; + int todo; + + /* "fc" is still in use. This can happen when returning "a:000" or + * assigning "l:" to a global variable. + * Link "fc" in the list for garbage collection later. */ + fc->caller = previous_funccal; + previous_funccal = fc; + + /* Make a copy of the a: variables, since we didn't do that above. */ + todo = (int)fc->l_avars.dv_hashtab.ht_used; + for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + --todo; + v = HI2DI(hi); + copy_tv(&v->di_tv, &v->di_tv); + } + } + + /* Make a copy of the a:000 items, since we didn't do that above. */ + for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) + copy_tv(&li->li_tv, &li->li_tv); + } +} + +/* + * Return TRUE if items in "fc" do not have "copyID". That means they are not + * referenced from anywyere. + */ + static int +can_free_funccal(fc, copyID) + funccall_T *fc; + int copyID; +{ + return (fc->l_varlist.lv_copyID != copyID + && fc->l_vars.dv_copyID != copyID + && fc->l_avars.dv_copyID != copyID); +} + +/* + * Free "fc" and what it contains. + */ + static void +free_funccal(fc, free_val) + funccall_T *fc; + int free_val; /* a: vars were allocated */ +{ + listitem_T *li; + + /* The a: variables typevals may not have been allocated, only free the + * allocated variables. */ + vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); + + /* free all l: variables */ + vars_clear(&fc->l_vars.dv_hashtab); + + /* Free the a:000 variables if they were allocated. */ + if (free_val) + for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) + clear_tv(&li->li_tv); + + vim_free(fc); } /* diff --git a/src/ex_cmds.c b/src/ex_cmds.c index e3049fb058..45d8c81f17 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -1941,7 +1941,7 @@ write_viminfo(file, forceit) * root. */ if (fp_out != NULL) - (void)fchown(fileno(fp_out), st_old.st_uid, st_old.st_gid); + ignored = fchown(fileno(fp_out), st_old.st_uid, st_old.st_gid); #endif } } diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 9847b8d267..83828465d3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8773,8 +8773,8 @@ ex_mkrc(eap) else if (*dirnow != NUL && (ssop_flags & SSOP_CURDIR) && globaldir != NULL) { - (void)mch_chdir((char *)globaldir); - shorten_fnames(TRUE); + if (mch_chdir((char *)globaldir) == OK) + shorten_fnames(TRUE); } failed |= (makeopens(fd, dirnow) == FAIL); @@ -10134,7 +10134,7 @@ makeopens(fd, dirnow) */ if (put_line(fd, "let s:sx = expand(\":p:r\").\"x.vim\"") == FAIL || put_line(fd, "if file_readable(s:sx)") == FAIL - || put_line(fd, " exe \"source \" . s:sx") == FAIL + || put_line(fd, " exe \"source \" . fnameescape(s:sx)") == FAIL || put_line(fd, "endif") == FAIL) return FAIL; diff --git a/src/ex_getln.c b/src/ex_getln.c index f045c1a141..958de152a9 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -2524,7 +2524,7 @@ realloc_cmdbuff(len) && ccline.xpc->xp_context != EXPAND_NOTHING && ccline.xpc->xp_context != EXPAND_UNSUCCESSFUL) { - int i = ccline.xpc->xp_pattern - p; + int i = (int)(ccline.xpc->xp_pattern - p); /* If xp_pattern points inside the old cmdbuff it needs to be adjusted * to point into the newly allocated memory. */ @@ -4900,7 +4900,7 @@ ExpandRTDir(pat, num_file, file, dirname) if (s == NULL) return FAIL; sprintf((char *)s, "%s/%s*.vim", dirname, pat); - all = globpath(p_rtp, s); + all = globpath(p_rtp, s, 0); vim_free(s); if (all == NULL) return FAIL; @@ -4941,9 +4941,10 @@ ExpandRTDir(pat, num_file, file, dirname) * newlines. Returns NULL for an error or no matches. */ char_u * -globpath(path, file) +globpath(path, file, expand_options) char_u *path; char_u *file; + int expand_options; { expand_T xpc; char_u *buf; @@ -4972,10 +4973,10 @@ globpath(path, file) { add_pathsep(buf); STRCAT(buf, file); - if (ExpandFromContext(&xpc, buf, &num_p, &p, WILD_SILENT) != FAIL - && num_p > 0) + if (ExpandFromContext(&xpc, buf, &num_p, &p, + WILD_SILENT|expand_options) != FAIL && num_p > 0) { - ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT); + ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); for (len = 0, i = 0; i < num_p; ++i) len += (int)STRLEN(p[i]) + 1; diff --git a/src/fileio.c b/src/fileio.c index 3965d096bc..ac2cea6936 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2214,7 +2214,7 @@ failed: { /* Use stderr for stdin, makes shell commands work. */ close(0); - dup(2); + ignored = dup(2); } #endif @@ -3449,7 +3449,7 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit, { # ifdef UNIX # ifdef HAVE_FCHOWN - fchown(fd, st_old.st_uid, st_old.st_gid); + ignored = fchown(fd, st_old.st_uid, st_old.st_gid); # endif if (mch_stat((char *)IObuff, &st) < 0 || st.st_uid != st_old.st_uid @@ -4365,7 +4365,7 @@ restore_backup: || st.st_uid != st_old.st_uid || st.st_gid != st_old.st_gid) { - fchown(fd, st_old.st_uid, st_old.st_gid); + ignored = fchown(fd, st_old.st_uid, st_old.st_gid); if (perm >= 0) /* set permission again, may have changed */ (void)mch_setperm(wfname, perm); } @@ -6035,9 +6035,9 @@ vim_fgets(buf, size, fp) { tbuf[FGETS_SIZE - 2] = NUL; #ifdef USE_CR - fgets_cr((char *)tbuf, FGETS_SIZE, fp); + ignoredp = fgets_cr((char *)tbuf, FGETS_SIZE, fp); #else - fgets((char *)tbuf, FGETS_SIZE, fp); + ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp); #endif } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n'); } diff --git a/src/fold.c b/src/fold.c index b7b8ea744c..1fe7c5a1d9 100644 --- a/src/fold.c +++ b/src/fold.c @@ -48,7 +48,7 @@ static int checkCloseRec __ARGS((garray_T *gap, linenr_T lnum, int level)); static int foldFind __ARGS((garray_T *gap, linenr_T lnum, fold_T **fpp)); static int foldLevelWin __ARGS((win_T *wp, linenr_T lnum)); static void checkupdate __ARGS((win_T *wp)); -static void setFoldRepeat __ARGS((linenr_T lnum, long count, int open)); +static void setFoldRepeat __ARGS((linenr_T lnum, long count, int do_open)); static linenr_T setManualFold __ARGS((linenr_T lnum, int opening, int recurse, int *donep)); static linenr_T setManualFoldWin __ARGS((win_T *wp, linenr_T lnum, int opening, int recurse, int *donep)); static void foldOpenNested __ARGS((fold_T *fpr)); @@ -1241,10 +1241,10 @@ checkupdate(wp) * Repeat "count" times. */ static void -setFoldRepeat(lnum, count, open) +setFoldRepeat(lnum, count, do_open) linenr_T lnum; long count; - int open; + int do_open; { int done; long n; @@ -1252,7 +1252,7 @@ setFoldRepeat(lnum, count, open) for (n = 0; n < count; ++n) { done = DONE_NOTHING; - (void)setManualFold(lnum, open, FALSE, &done); + (void)setManualFold(lnum, do_open, FALSE, &done); if (!(done & DONE_ACTION)) { /* Only give an error message when no fold could be opened. */ diff --git a/src/getchar.c b/src/getchar.c index d4066c2124..081368d028 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -4702,7 +4702,7 @@ makemap(fd, buf) return FAIL; if (mp->m_noremap != REMAP_YES && fprintf(fd, "nore") < 0) return FAIL; - if (fprintf(fd, cmd) < 0) + if (fputs(cmd, fd) < 0) return FAIL; if (buf != NULL && fputs(" ", fd) < 0) return FAIL; @@ -4801,7 +4801,7 @@ put_escstr(fd, strstart, what) } if (IS_SPECIAL(c) || modifiers) /* special key */ { - if (fprintf(fd, (char *)get_special_key_name(c, modifiers)) < 0) + if (fputs((char *)get_special_key_name(c, modifiers), fd) < 0) return FAIL; continue; } diff --git a/src/globals.h b/src/globals.h index 37bcdb5442..29f5b62adc 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1550,6 +1550,14 @@ EXTERN int xsmp_icefd INIT(= -1); /* The actual connection */ /* For undo we need to know the lowest time possible. */ EXTERN time_t starttime; +/* + * Some compilers warn for not using a return value, but in some situations we + * can't do anything useful with the value. Assign to this variable to avoid + * the warning. + */ +EXTERN int ignored; +EXTERN char *ignoredp; + /* * Optional Farsi support. Include it here, so EXTERN and INIT are defined. */ diff --git a/src/gui.c b/src/gui.c index dcdd4e9e9a..196a55e322 100644 --- a/src/gui.c +++ b/src/gui.c @@ -211,7 +211,7 @@ http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/fork.2.h /* The read returns when the child closes the pipe (or when * the child dies for some reason). */ close(pipefd[1]); - (void)read(pipefd[0], &dummy, (size_t)1); + ignored = (int)read(pipefd[0], &dummy, (size_t)1); close(pipefd[0]); } @@ -3333,7 +3333,7 @@ gui_init_which_components(oldval) i = Rows; gui_update_tabline(); Rows = i; - need_set_size = RESIZE_VERT; + need_set_size |= RESIZE_VERT; if (using_tabline) fix_size = TRUE; if (!gui_use_tabline()) @@ -3367,9 +3367,9 @@ gui_init_which_components(oldval) if (gui.which_scrollbars[i] != prev_which_scrollbars[i]) { if (i == SBAR_BOTTOM) - need_set_size = RESIZE_VERT; + need_set_size |= RESIZE_VERT; else - need_set_size = RESIZE_HOR; + need_set_size |= RESIZE_HOR; if (gui.which_scrollbars[i]) fix_size = TRUE; } @@ -3389,7 +3389,7 @@ gui_init_which_components(oldval) gui_mch_enable_menu(gui.menu_is_active); Rows = i; prev_menu_is_active = gui.menu_is_active; - need_set_size = RESIZE_VERT; + need_set_size |= RESIZE_VERT; if (gui.menu_is_active) fix_size = TRUE; } @@ -3400,7 +3400,7 @@ gui_init_which_components(oldval) { gui_mch_show_toolbar(using_toolbar); prev_toolbar = using_toolbar; - need_set_size = RESIZE_VERT; + need_set_size |= RESIZE_VERT; if (using_toolbar) fix_size = TRUE; } @@ -3410,7 +3410,7 @@ gui_init_which_components(oldval) { gui_mch_enable_footer(using_footer); prev_footer = using_footer; - need_set_size = RESIZE_VERT; + need_set_size |= RESIZE_VERT; if (using_footer) fix_size = TRUE; } @@ -3422,10 +3422,11 @@ gui_init_which_components(oldval) prev_tearoff = using_tearoff; } #endif - if (need_set_size) + if (need_set_size != 0) { #ifdef FEAT_GUI_GTK - long c = Columns; + long prev_Columns = Columns; + long prev_Rows = Rows; #endif /* Adjust the size of the window to make the text area keep the * same size and to avoid that part of our window is off-screen @@ -3441,11 +3442,14 @@ gui_init_which_components(oldval) * If you remove this, please test this command for resizing * effects (with optional left scrollbar): ":vsp|q|vsp|q|vsp|q". * Don't do this while starting up though. - * And don't change Rows, it may have be reduced intentionally - * when adding menu/toolbar/tabline. */ - if (!gui.starting) + * Don't change Rows when adding menu/toolbar/tabline. + * Don't change Columns when adding vertical toolbar. */ + if (!gui.starting && need_set_size != (RESIZE_VERT | RESIZE_HOR)) (void)char_avail(); - Columns = c; + if ((need_set_size & RESIZE_VERT) == 0) + Rows = prev_Rows; + if ((need_set_size & RESIZE_HOR) == 0) + Columns = prev_Columns; #endif } #ifdef FEAT_WINDOWS diff --git a/src/gui_at_sb.c b/src/gui_at_sb.c index 5fe3afbbe8..1726953a22 100644 --- a/src/gui_at_sb.c +++ b/src/gui_at_sb.c @@ -1078,6 +1078,12 @@ NotifyThumb(w, event, params, num_params) Cardinal *num_params; /* unused */ { ScrollbarWidget sbw = (ScrollbarWidget)w; + /* Use a union to avoid a warning for the weird conversion from float to + * XtPointer. Comes from Xaw/Scrollbar.c. */ + union { + XtPointer xtp; + float xtf; + } xtpf; if (LookAhead(w, event)) return; @@ -1085,7 +1091,8 @@ NotifyThumb(w, event, params, num_params) /* thumbProc is not pretty, but is necessary for backwards compatibility on those architectures for which it work{s,ed}; the intent is to pass a (truncated) float by value. */ - XtCallCallbacks(w, XtNthumbProc, *(XtPointer*)&sbw->scrollbar.top); + xtpf.xtf = sbw->scrollbar.top; + XtCallCallbacks(w, XtNthumbProc, xtpf.xtp); XtCallCallbacks(w, XtNjumpProc, (XtPointer)&sbw->scrollbar.top); } diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index dc95d818ad..cd6555767b 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -4070,14 +4070,14 @@ gui_mch_open(void) if (mask & (XValue | YValue)) { - int w, h; - gui_mch_get_screen_dimensions(&w, &h); - h += p_ghr + get_menu_tool_height(); - w += get_menu_tool_width(); + int ww, hh; + gui_mch_get_screen_dimensions(&ww, &hh); + hh += p_ghr + get_menu_tool_height(); + ww += get_menu_tool_width(); if (mask & XNegative) - x += w - pixel_width; + x += ww - pixel_width; if (mask & YNegative) - y += h - pixel_height; + y += hh - pixel_height; #ifdef HAVE_GTK2 gtk_window_move(GTK_WINDOW(gui.mainwin), x, y); #else diff --git a/src/gui_mac.c b/src/gui_mac.c index d54c110050..9112c56b71 100644 --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -4966,7 +4966,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx) char_u *p_actext; p_actext = menu->actext; - key = find_special_key(&p_actext, &modifiers, /*keycode=*/0); + key = find_special_key(&p_actext, &modifiers, FALSE, FALSE); if (*p_actext != 0) key = 0; /* error: trailing text */ /* find_special_key() returns a keycode with as many of the diff --git a/src/gui_w48.c b/src/gui_w48.c index 08dcb2d0a2..4de0c76392 100644 --- a/src/gui_w48.c +++ b/src/gui_w48.c @@ -1937,6 +1937,11 @@ gui_mch_wait_for_chars(int wtime) s_need_activate = FALSE; } +#ifdef FEAT_NETBEANS_INTG + /* Process the queued netbeans messages. */ + netbeans_parse_messages(); +#endif + /* * Don't use gui_mch_update() because then we will spin-lock until a * char arrives, instead we use GetMessage() to hang until an diff --git a/src/gui_xmdlg.c b/src/gui_xmdlg.c index 95e3268e33..cbdbe681d2 100644 --- a/src/gui_xmdlg.c +++ b/src/gui_xmdlg.c @@ -369,10 +369,10 @@ fill_lists(enum ListSpecifier fix, SharedFontSelData *data) char buf[TEMP_BUF_SIZE]; XmString items[MAX_ENTRIES_IN_LIST]; int i; - int index; + int idx; - for (index = (int)ENCODING; index < (int)NONE; ++index) - count[index] = 0; + for (idx = (int)ENCODING; idx < (int)NONE; ++idx) + count[idx] = 0; /* First we insert the wild char into every single list. */ if (fix != ENCODING) @@ -503,14 +503,14 @@ fill_lists(enum ListSpecifier fix, SharedFontSelData *data) /* * Now loop trough the remaining lists and set them up. */ - for (index = (int)NAME; index < (int)NONE; ++index) + for (idx = (int)NAME; idx < (int)NONE; ++idx) { Widget w; - if (fix == (enum ListSpecifier)index) + if (fix == (enum ListSpecifier)idx) continue; - switch ((enum ListSpecifier)index) + switch ((enum ListSpecifier)idx) { case NAME: w = data->list[NAME]; @@ -525,21 +525,21 @@ fill_lists(enum ListSpecifier fix, SharedFontSelData *data) w = (Widget)0; /* for lint */ } - for (i = 0; i < count[index]; ++i) + for (i = 0; i < count[idx]; ++i) { - items[i] = XmStringCreateLocalized(list[index][i]); - XtFree(list[index][i]); + items[i] = XmStringCreateLocalized(list[idx][i]); + XtFree(list[idx][i]); } XmListDeleteAllItems(w); - XmListAddItems(w, items, count[index], 1); - if (data->sel[index]) + XmListAddItems(w, items, count[idx], 1); + if (data->sel[idx]) { XmStringFree(items[0]); - items[0] = XmStringCreateLocalized(data->sel[index]); + items[0] = XmStringCreateLocalized(data->sel[idx]); XmListSelectItem(w, items[0], False); XmListSetBottomItem(w, items[0]); } - for (i = 0; i < count[index]; ++i) + for (i = 0; i < count[idx]; ++i) XmStringFree(items[i]); } } @@ -695,14 +695,14 @@ do_choice(Widget w, int n; XmString str; Arg args[4]; - char *msg = _("no specific match"); + char *nomatch_msg = _("no specific match"); n = 0; - str = XmStringCreateLocalized(msg); + str = XmStringCreateLocalized(nomatch_msg); XtSetArg(args[n], XmNlabelString, str); ++n; XtSetValues(data->sample, args, n); apply_fontlist(data->sample); - XmTextSetString(data->name, msg); + XmTextSetString(data->name, nomatch_msg); XmStringFree(str); return False; @@ -886,21 +886,21 @@ gui_xm_select_font(char_u *current) { int i; int max; - int index = 0; + int idx = 0; int size; - char str[128]; + char buf[128]; for (i = 0, max = 0; i < data->num; i++) { - get_part(fn(data, i), 7, str); - size = atoi(str); + get_part(fn(data, i), 7, buf); + size = atoi(buf); if ((size > max) && (size < MAX_DISPLAY_SIZE)) { - index = i; + idx = i; max = size; } } - strcpy(big_font, fn(data, index)); + strcpy(big_font, fn(data, idx)); } data->old = XLoadQueryFont(XtDisplay(parent), big_font); data->old_list = gui_motif_create_fontlist(data->old); @@ -1217,28 +1217,28 @@ gui_xm_select_font(char_u *current) if (i != 0) { - char name[TEMP_BUF_SIZE]; - char style[TEMP_BUF_SIZE]; - char size[TEMP_BUF_SIZE]; - char encoding[TEMP_BUF_SIZE]; + char namebuf[TEMP_BUF_SIZE]; + char stylebuf[TEMP_BUF_SIZE]; + char sizebuf[TEMP_BUF_SIZE]; + char encodingbuf[TEMP_BUF_SIZE]; char *found; found = names[0]; - name_part(found, name); - style_part(found, style); - size_part(found, size, data->in_pixels); - encoding_part(found, encoding); + name_part(found, namebuf); + style_part(found, stylebuf); + size_part(found, sizebuf, data->in_pixels); + encoding_part(found, encodingbuf); - if (strlen(name) > 0 - && strlen(style) > 0 - && strlen(size) > 0 - && strlen(encoding) > 0) + if (strlen(namebuf) > 0 + && strlen(stylebuf) > 0 + && strlen(sizebuf) > 0 + && strlen(encodingbuf) > 0) { - data->sel[NAME] = XtNewString(name); - data->sel[STYLE] = XtNewString(style); - data->sel[SIZE] = XtNewString(size); - data->sel[ENCODING] = XtNewString(encoding); + data->sel[NAME] = XtNewString(namebuf); + data->sel[STYLE] = XtNewString(stylebuf); + data->sel[SIZE] = XtNewString(sizebuf); + data->sel[ENCODING] = XtNewString(encodingbuf); data->font_name = XtNewString(names[0]); display_sample(data); XmTextSetString(data->name, data->font_name); diff --git a/src/gui_xmebw.c b/src/gui_xmebw.c index 77b59c2408..3e134ce9d6 100644 --- a/src/gui_xmebw.c +++ b/src/gui_xmebw.c @@ -1256,7 +1256,7 @@ Redisplay(Widget w, XEvent *event, Region region) } else { - int adjust = 0; + adjust = 0; #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) /* @@ -1268,12 +1268,11 @@ Redisplay(Widget w, XEvent *event, Region region) { case XmEXTERNAL_HIGHLIGHT: adjust = (eb->primitive.highlight_thickness - - (eb->pushbutton.default_button_shadow_thickness ? - Xm3D_ENHANCE_PIXEL : 0)); + (eb->pushbutton.default_button_shadow_thickness + ? Xm3D_ENHANCE_PIXEL : 0)); break; case XmINTERNAL_HIGHLIGHT: - adjust = 0; break; default: diff --git a/src/if_perl.xs b/src/if_perl.xs index 78a91aafd5..2d5ab462e2 100644 --- a/src/if_perl.xs +++ b/src/if_perl.xs @@ -166,7 +166,7 @@ EXTERN_C void boot_DynaLoader __ARGS((pTHX_ CV*)); # define Perl_Isv_yes_ptr dll_Perl_Isv_yes_ptr # define boot_DynaLoader dll_boot_DynaLoader -# define Perl_sys_init3 dll_Perl_sys_init3 +# define Perl_sys_init dll_Perl_sys_init # define Perl_sys_term dll_Perl_sys_term # define Perl_ISv_ptr dll_Perl_ISv_ptr # define Perl_Istack_max_ptr dll_Perl_Istack_max_ptr @@ -272,7 +272,7 @@ static void (*boot_DynaLoader)_((pTHX_ CV*)); #if (PERL_REVISION == 5) && (PERL_VERSION >= 10) static void (*Perl_sv_free2)(pTHX_ SV*); -static void (*Perl_sys_init3)(int* argc, char*** argv, char*** env); +static void (*Perl_sys_init)(int* argc, char*** argv); static void (*Perl_sys_term)(void); static SV** (*Perl_ISv_ptr)(register PerlInterpreter*); static SV*** (*Perl_Istack_max_ptr)(register PerlInterpreter*); @@ -372,7 +372,7 @@ static struct { {"Perl_Tna_ptr", (PERL_PROC*)&Perl_Tna_ptr}, #else {"Perl_sv_free2", (PERL_PROC*)&Perl_sv_free2}, - {"Perl_sys_init3", (PERL_PROC*)&Perl_sys_init3}, + {"Perl_sys_init", (PERL_PROC*)&Perl_sys_init}, {"Perl_sys_term", (PERL_PROC*)&Perl_sys_term}, {"Perl_ISv_ptr", (PERL_PROC*)&Perl_ISv_ptr}, {"Perl_Istack_sp_ptr", (PERL_PROC*)&Perl_Istack_sp_ptr}, @@ -460,7 +460,7 @@ perl_init() static char *argv[] = { "", "-e", "" }; #if (PERL_REVISION == 5) && (PERL_VERSION >= 10) - Perl_sys_init3(&argc, (char***)&argv, NULL); + Perl_sys_init(&argc, (char***)&argv); #endif perl_interp = perl_alloc(); perl_construct(perl_interp); diff --git a/src/if_sniff.c b/src/if_sniff.c index 34b0128963..cf38e534cb 100644 --- a/src/if_sniff.c +++ b/src/if_sniff.c @@ -2,8 +2,6 @@ * * if_sniff.c Interface between Vim and SNiFF+ * - * $Id$ - * * See README.txt for an overview of the Vim source code. */ @@ -716,8 +714,10 @@ ConnectToSniffEmacs() #else /* UNIX Version of the Code */ int ToSniffEmacs[2], FromSniffEmacs[2]; - pipe(ToSniffEmacs); - pipe(FromSniffEmacs); + if (pipe(ToSniffEmacs) != 0) + return 1; + if (pipe(FromSniffEmacs) != 0) + return 1; /* fork */ if ((sniffemacs_pid=fork()) == 0) diff --git a/src/main.c b/src/main.c index 41cf21ca3a..80ad39e209 100644 --- a/src/main.c +++ b/src/main.c @@ -2458,7 +2458,7 @@ read_stdin() * Is there any other system that cannot do this? */ close(0); - dup(2); + ignored = dup(2); #endif } diff --git a/src/mbyte.c b/src/mbyte.c index a2ffd7e5f9..42b3063a0e 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -717,7 +717,7 @@ codepage_invalid: * where mblen() returns 0 for invalid character. * Therefore, following condition includes 0. */ - (void)mblen(NULL, 0); /* First reset the state. */ + ignored = mblen(NULL, 0); /* First reset the state. */ if (mblen(buf, (size_t)1) <= 0) n = 2; else @@ -5278,7 +5278,7 @@ xim_decide_input_style() /*ARGSUSED*/ static void -preedit_start_cbproc(XIC xic, XPointer client_data, XPointer call_data) +preedit_start_cbproc(XIC thexic, XPointer client_data, XPointer call_data) { #ifdef XIM_DEBUG xim_log("xim_decide_input_style()\n"); @@ -5312,7 +5312,7 @@ static gboolean processing_queued_event = FALSE; /*ARGSUSED*/ static void -preedit_draw_cbproc(XIC xic, XPointer client_data, XPointer call_data) +preedit_draw_cbproc(XIC thexic, XPointer client_data, XPointer call_data) { XIMPreeditDrawCallbackStruct *draw_data; XIMText *text; @@ -5453,7 +5453,7 @@ im_get_feedback_attr(int col) /*ARGSUSED*/ static void -preedit_caret_cbproc(XIC xic, XPointer client_data, XPointer call_data) +preedit_caret_cbproc(XIC thexic, XPointer client_data, XPointer call_data) { #ifdef XIM_DEBUG xim_log("preedit_caret_cbproc()\n"); @@ -5462,7 +5462,7 @@ preedit_caret_cbproc(XIC xic, XPointer client_data, XPointer call_data) /*ARGSUSED*/ static void -preedit_done_cbproc(XIC xic, XPointer client_data, XPointer call_data) +preedit_done_cbproc(XIC thexic, XPointer client_data, XPointer call_data) { #ifdef XIM_DEBUG xim_log("preedit_done_cbproc()\n"); diff --git a/src/message.c b/src/message.c index bf340d04de..548a89eed0 100644 --- a/src/message.c +++ b/src/message.c @@ -4585,61 +4585,62 @@ vim_snprintf(str, str_m, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) if (remove_trailing_zeroes) { int i; - char *p; + char *tp; /* Using %g or %G: remove superfluous zeroes. */ if (fmt_spec == 'f') - p = tmp + str_arg_l - 1; + tp = tmp + str_arg_l - 1; else { - p = (char *)vim_strchr((char_u *)tmp, + tp = (char *)vim_strchr((char_u *)tmp, fmt_spec == 'e' ? 'e' : 'E'); - if (p != NULL) + if (tp != NULL) { /* Remove superfluous '+' and leading * zeroes from the exponent. */ - if (p[1] == '+') + if (tp[1] == '+') { /* Change "1.0e+07" to "1.0e07" */ - STRMOVE(p + 1, p + 2); + STRMOVE(tp + 1, tp + 2); --str_arg_l; } - i = (p[1] == '-') ? 2 : 1; - while (p[i] == '0') + i = (tp[1] == '-') ? 2 : 1; + while (tp[i] == '0') { /* Change "1.0e07" to "1.0e7" */ - STRMOVE(p + i, p + i + 1); + STRMOVE(tp + i, tp + i + 1); --str_arg_l; } - --p; + --tp; } } - if (p != NULL && !precision_specified) + if (tp != NULL && !precision_specified) /* Remove trailing zeroes, but keep the one * just after a dot. */ - while (p > tmp + 2 && *p == '0' && p[-1] != '.') + while (tp > tmp + 2 && *tp == '0' + && tp[-1] != '.') { - STRMOVE(p, p + 1); - --p; + STRMOVE(tp, tp + 1); + --tp; --str_arg_l; } } else { - char *p; + char *tp; /* Be consistent: some printf("%e") use 1.0e+12 * and some 1.0e+012. Remove one zero in the last * case. */ - p = (char *)vim_strchr((char_u *)tmp, + tp = (char *)vim_strchr((char_u *)tmp, fmt_spec == 'e' ? 'e' : 'E'); - if (p != NULL && (p[1] == '+' || p[1] == '-') - && p[2] == '0' - && vim_isdigit(p[3]) - && vim_isdigit(p[4])) + if (tp != NULL && (tp[1] == '+' || tp[1] == '-') + && tp[2] == '0' + && vim_isdigit(tp[3]) + && vim_isdigit(tp[4])) { - STRMOVE(p + 2, p + 3); + STRMOVE(tp + 2, tp + 3); --str_arg_l; } } diff --git a/src/misc2.c b/src/misc2.c index 4d40ad207e..76fe2ec519 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2561,7 +2561,7 @@ trans_special(srcp, dst, keycode) int key; int dlen = 0; - key = find_special_key(srcp, &modifiers, keycode); + key = find_special_key(srcp, &modifiers, keycode, FALSE); if (key == 0) return 0; @@ -2597,10 +2597,11 @@ trans_special(srcp, dst, keycode) * returns 0 if there is no match. */ int -find_special_key(srcp, modp, keycode) +find_special_key(srcp, modp, keycode, keep_x_key) char_u **srcp; int *modp; - int keycode; /* prefer key code, e.g. K_DEL instead of DEL */ + int keycode; /* prefer key code, e.g. K_DEL instead of DEL */ + int keep_x_key; /* don't translate xHome to Home key */ { char_u *last_dash; char_u *end_of_name; @@ -2668,7 +2669,8 @@ find_special_key(srcp, modp, keycode) else { key = get_special_key_code(last_dash + 1); - key = handle_x_keys(key); + if (!keep_x_key) + key = handle_x_keys(key); } /* diff --git a/src/netbeans.c b/src/netbeans.c index 19c365054f..67301767da 100644 --- a/src/netbeans.c +++ b/src/netbeans.c @@ -769,11 +769,14 @@ messageFromNetbeans(gpointer clientData, gint unused1, return; /* don't try to parse it */ } -#ifdef FEAT_GUI_GTK +#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) + /* Let the main loop handle messages. */ +# ifdef FEAT_GUI_GTK if (gtk_main_level() > 0) gtk_main_quit(); +# endif #else - /* Parse the messages, but avoid recursion. */ + /* Parse the messages now, but avoid recursion. */ if (level == 1) netbeans_parse_messages(); @@ -1043,7 +1046,7 @@ netbeans_end(void) nbdebug(("EVT: %s", buf)); /* nb_send(buf, "netbeans_end"); avoid "write failed" messages */ if (sd >= 0) - sock_write(sd, buf, (int)STRLEN(buf)); /* ignore errors */ + ignored = sock_write(sd, buf, (int)STRLEN(buf)); } } @@ -2277,9 +2280,6 @@ nb_do_cmd( int serNum; int localTypeNum; int typeNum; -# ifdef NBDEBUG - int len; -# endif pos_T *pos; if (buf == NULL || buf->bufp == NULL) @@ -2303,13 +2303,10 @@ nb_do_cmd( pos = get_off_or_lnum(buf->bufp, &args); cp = (char *)args; -# ifdef NBDEBUG - len = -# endif - strtol(cp, &cp, 10); + ignored = (int)strtol(cp, &cp, 10); args = (char_u *)cp; # ifdef NBDEBUG - if (len != -1) + if (ignored != -1) { nbdebug((" partial line annotation -- Not Yet Implemented!\n")); } diff --git a/src/ops.c b/src/ops.c index d79d75d52b..557985c38a 100644 --- a/src/ops.c +++ b/src/ops.c @@ -2209,12 +2209,15 @@ op_tilde(oap) { for (; pos.lnum <= oap->end.lnum; ++pos.lnum) { + int one_change; + block_prep(oap, &bd, pos.lnum, FALSE); pos.col = bd.textcol; - did_change = swapchars(oap->op_type, &pos, bd.textlen); + one_change = swapchars(oap->op_type, &pos, bd.textlen); + did_change |= one_change; # ifdef FEAT_NETBEANS_INTG - if (usingNetbeans && did_change) + if (usingNetbeans && one_change) { char_u *ptr = ml_get_buf(curbuf, pos.lnum, FALSE); diff --git a/src/option.c b/src/option.c index 8a39fb0e5b..fc2f7d9854 100644 --- a/src/option.c +++ b/src/option.c @@ -8360,13 +8360,13 @@ set_option_value(name, number, string, opt_flags) { if (number == 0 && string != NULL) { - int index; + int idx; /* Either we are given a string or we are setting option * to zero. */ - for (index = 0; string[index] == '0'; ++index) + for (idx = 0; string[idx] == '0'; ++idx) ; - if (string[index] != NUL || index == 0) + if (string[idx] != NUL || idx == 0) { /* There's another character after zeros or the string * is empty. In both cases, we are trying to set a @@ -8456,7 +8456,7 @@ find_key_option(arg) { --arg; /* put arg at the '<' */ modifiers = 0; - key = find_special_key(&arg, &modifiers, TRUE); + key = find_special_key(&arg, &modifiers, TRUE, TRUE); if (modifiers) /* can't handle modifiers here */ key = 0; } diff --git a/src/os_unix.c b/src/os_unix.c index c9dcbd9c7f..8e285e5e8a 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -315,12 +315,15 @@ static struct signalinfo {-1, "Unknown!", FALSE} }; +/* + * Write s[len] to the screen. + */ void mch_write(s, len) char_u *s; int len; { - write(1, (char *)s, len); + ignored = (int)write(1, (char *)s, len); if (p_wd) /* Unix is too fast, slow down a bit more */ RealWaitForChar(read_cmd_fd, p_wd, NULL); } @@ -3929,9 +3932,9 @@ mch_call_shell(cmd, options) */ if (fd >= 0) { - dup(fd); /* To replace stdin (file descriptor 0) */ - dup(fd); /* To replace stdout (file descriptor 1) */ - dup(fd); /* To replace stderr (file descriptor 2) */ + ignored = dup(fd); /* To replace stdin (fd 0) */ + ignored = dup(fd); /* To replace stdout (fd 1) */ + ignored = dup(fd); /* To replace stderr (fd 2) */ /* Don't need this now that we've duplicated it */ close(fd); @@ -3999,13 +4002,13 @@ mch_call_shell(cmd, options) /* set up stdin/stdout/stderr for the child */ close(0); - dup(pty_slave_fd); + ignored = dup(pty_slave_fd); close(1); - dup(pty_slave_fd); + ignored = dup(pty_slave_fd); if (gui.in_use) { close(2); - dup(pty_slave_fd); + ignored = dup(pty_slave_fd); } close(pty_slave_fd); /* has been dupped, close it now */ @@ -4016,13 +4019,13 @@ mch_call_shell(cmd, options) /* set up stdin for the child */ close(fd_toshell[1]); close(0); - dup(fd_toshell[0]); + ignored = dup(fd_toshell[0]); close(fd_toshell[0]); /* set up stdout for the child */ close(fd_fromshell[0]); close(1); - dup(fd_fromshell[1]); + ignored = dup(fd_fromshell[1]); close(fd_fromshell[1]); # ifdef FEAT_GUI @@ -4030,7 +4033,7 @@ mch_call_shell(cmd, options) { /* set up stderr for the child */ close(2); - dup(1); + ignored = dup(1); } # endif } @@ -4161,7 +4164,8 @@ mch_call_shell(cmd, options) && (lnum != curbuf->b_ml.ml_line_count || curbuf->b_p_eol))) - write(toshell_fd, "\n", (size_t)1); + ignored = write(toshell_fd, "\n", + (size_t)1); ++lnum; if (lnum > curbuf->b_op_end.lnum) { diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro index b4a5018143..afbf664699 100644 --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -31,7 +31,7 @@ char_u *addstar __ARGS((char_u *fname, int len, int context)); void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col)); int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches)); int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)))); -char_u *globpath __ARGS((char_u *path, char_u *file)); +char_u *globpath __ARGS((char_u *path, char_u *file, int expand_options)); void init_history __ARGS((void)); int get_histtype __ARGS((char_u *name)); void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep)); diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index c386a0d4c0..261ec8226d 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -59,7 +59,7 @@ int simplify_key __ARGS((int key, int *modifiers)); int handle_x_keys __ARGS((int key)); char_u *get_special_key_name __ARGS((int c, int modifiers)); int trans_special __ARGS((char_u **srcp, char_u *dst, int keycode)); -int find_special_key __ARGS((char_u **srcp, int *modp, int keycode)); +int find_special_key __ARGS((char_u **srcp, int *modp, int keycode, int keep_x_key)); int extract_modifiers __ARGS((int key, int *modp)); int find_special_key_in_table __ARGS((int c)); int get_special_key_code __ARGS((char_u *name)); diff --git a/src/spell.c b/src/spell.c index 53869bbcaa..b89ef8365f 100644 --- a/src/spell.c +++ b/src/spell.c @@ -469,6 +469,7 @@ struct slang_S garray_T sl_comppat; /* CHECKCOMPOUNDPATTERN items */ regprog_T *sl_compprog; /* COMPOUNDRULE turned into a regexp progrm * (NULL when no compounding) */ + char_u *sl_comprules; /* all COMPOUNDRULE concatenated (or NULL) */ char_u *sl_compstartflags; /* flags for first compound word */ char_u *sl_compallflags; /* all flags for compound words */ char_u sl_nobreak; /* When TRUE: no spaces between words */ @@ -839,7 +840,10 @@ static void slang_free __ARGS((slang_T *lp)); static void slang_clear __ARGS((slang_T *lp)); static void slang_clear_sug __ARGS((slang_T *lp)); static void find_word __ARGS((matchinf_T *mip, int mode)); +static int match_checkcompoundpattern __ARGS((char_u *ptr, int wlen, garray_T *gap)); static int can_compound __ARGS((slang_T *slang, char_u *word, char_u *flags)); +static int can_be_compound __ARGS((trystate_T *sp, slang_T *slang, char_u *compflags, int flag)); +static int match_compoundrule __ARGS((slang_T *slang, char_u *compflags)); static int valid_word_prefix __ARGS((int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req)); static void find_prefix __ARGS((matchinf_T *mip, int mode)); static int fold_more __ARGS((matchinf_T *mip)); @@ -1519,6 +1523,11 @@ find_word(mip, mode) ((unsigned)flags >> 24))) continue; + /* If there is a match with a CHECKCOMPOUNDPATTERN rule + * discard the compound word. */ + if (match_checkcompoundpattern(ptr, wlen, &slang->sl_comppat)) + continue; + if (mode == FIND_COMPOUND) { int capflags; @@ -1577,6 +1586,11 @@ find_word(mip, mode) if (!can_compound(slang, fword, mip->mi_compflags)) continue; } + else if (slang->sl_comprules != NULL + && !match_compoundrule(slang, mip->mi_compflags)) + /* The compound flags collected so far do not match any + * COMPOUNDRULE, discard the compounded word. */ + continue; } /* Check NEEDCOMPOUND: can't use word without compounding. */ @@ -1726,6 +1740,39 @@ find_word(mip, mode) } } +/* + * Return TRUE if there is a match between the word ptr[wlen] and + * CHECKCOMPOUNDPATTERN rules, assuming that we will concatenate with another + * word. + * A match means that the first part of CHECKCOMPOUNDPATTERN matches at the + * end of ptr[wlen] and the second part matches after it. + */ + static int +match_checkcompoundpattern(ptr, wlen, gap) + char_u *ptr; + int wlen; + garray_T *gap; /* &sl_comppat */ +{ + int i; + char_u *p; + int len; + + for (i = 0; i + 1 < gap->ga_len; i += 2) + { + p = ((char_u **)gap->ga_data)[i + 1]; + if (STRNCMP(ptr + wlen, p, STRLEN(p)) == 0) + { + /* Second part matches at start of following compound word, now + * check if first part matches at end of previous word. */ + p = ((char_u **)gap->ga_data)[i]; + len = (int)STRLEN(p); + if (len <= wlen && STRNCMP(ptr + wlen - len, p, len) == 0) + return TRUE; + } + } + return FALSE; +} + /* * Return TRUE if "flags" is a valid sequence of compound flags and "word" * does not have too many syllables. @@ -1772,6 +1819,98 @@ can_compound(slang, word, flags) return TRUE; } +/* + * Return TRUE when the sequence of flags in "compflags" plus "flag" can + * possibly form a valid compounded word. This also checks the COMPOUNDRULE + * lines if they don't contain wildcards. + */ + static int +can_be_compound(sp, slang, compflags, flag) + trystate_T *sp; + slang_T *slang; + char_u *compflags; + int flag; +{ + /* If the flag doesn't appear in sl_compstartflags or sl_compallflags + * then it can't possibly compound. */ + if (!byte_in_str(sp->ts_complen == sp->ts_compsplit + ? slang->sl_compstartflags : slang->sl_compallflags, flag)) + return FALSE; + + /* If there are no wildcards, we can check if the flags collected so far + * possibly can form a match with COMPOUNDRULE patterns. This only + * makes sense when we have two or more words. */ + if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit) + { + int v; + + compflags[sp->ts_complen] = flag; + compflags[sp->ts_complen + 1] = NUL; + v = match_compoundrule(slang, compflags + sp->ts_compsplit); + compflags[sp->ts_complen] = NUL; + return v; + } + + return TRUE; +} + + +/* + * Return TRUE if the compound flags in compflags[] match the start of any + * compound rule. This is used to stop trying a compound if the flags + * collected so far can't possibly match any compound rule. + * Caller must check that slang->sl_comprules is not NULL. + */ + static int +match_compoundrule(slang, compflags) + slang_T *slang; + char_u *compflags; +{ + char_u *p; + int i; + int c; + + /* loop over all the COMPOUNDRULE entries */ + for (p = slang->sl_comprules; *p != NUL; ++p) + { + /* loop over the flags in the compound word we have made, match + * them against the current rule entry */ + for (i = 0; ; ++i) + { + c = compflags[i]; + if (c == NUL) + /* found a rule that matches for the flags we have so far */ + return TRUE; + if (*p == '/' || *p == NUL) + break; /* end of rule, it's too short */ + if (*p == '[') + { + int match = FALSE; + + /* compare against all the flags in [] */ + ++p; + while (*p != ']' && *p != NUL) + if (*p++ == c) + match = TRUE; + if (!match) + break; /* none matches */ + } + else if (*p != c) + break; /* flag of word doesn't match flag in pattern */ + ++p; + } + + /* Skip to the next "/", where the next pattern starts. */ + p = vim_strchr(p, '/'); + if (p == NULL) + break; + } + + /* Checked all the rules and none of them match the flags, so there + * can't possibly be a compound starting with these flags. */ + return FALSE; +} + /* * Return non-zero if the prefix indicated by "arridx" matches with the prefix * ID in "flags" for the word "word". @@ -2513,9 +2652,11 @@ slang_clear(lp) lp->sl_midword = NULL; vim_free(lp->sl_compprog); + vim_free(lp->sl_comprules); vim_free(lp->sl_compstartflags); vim_free(lp->sl_compallflags); lp->sl_compprog = NULL; + lp->sl_comprules = NULL; lp->sl_compstartflags = NULL; lp->sl_compallflags = NULL; @@ -3460,6 +3601,7 @@ read_compound(fd, slang, len) char_u *pp; char_u *cp; char_u *ap; + char_u *crp; int cnt; garray_T *gap; @@ -3545,6 +3687,12 @@ read_compound(fd, slang, len) slang->sl_compallflags = ap; *ap = NUL; + /* And a list of all patterns in their original form, for checking whether + * compounding may work in match_compoundrule(). This is freed when we + * encounter a wildcard, the check doesn't work then. */ + crp = alloc(todo + 1); + slang->sl_comprules = crp; + pp = pat; *pp++ = '^'; *pp++ = '\\'; @@ -3587,6 +3735,20 @@ read_compound(fd, slang, len) atstart = 0; } } + + /* Copy flag to "sl_comprules", unless we run into a wildcard. */ + if (crp != NULL) + { + if (c == '+' || c == '*') + { + vim_free(slang->sl_comprules); + slang->sl_comprules = NULL; + crp = NULL; + } + else + *crp++ = c; + } + if (c == '/') /* slash separates two items */ { *pp++ = '\\'; @@ -3611,6 +3773,9 @@ read_compound(fd, slang, len) *pp++ = '$'; *pp = NUL; + if (crp != NULL) + *crp = NUL; + slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT); vim_free(pat); if (slang->sl_compprog == NULL) @@ -4915,6 +5080,7 @@ typedef struct spellinfo_S } spellinfo_T; static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname)); +static int is_aff_rule __ARGS((char_u **items, int itemcnt, char *rulename, int mincount)); static void aff_process_flags __ARGS((afffile_T *affile, affentry_T *entry)); static int spell_info_item __ARGS((char_u *s)); static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u *fname, int lnum)); @@ -4950,7 +5116,7 @@ static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2)); static void put_sugtime __ARGS((spellinfo_T *spin, FILE *fd)); static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname)); static void clear_node __ARGS((wordnode_T *node)); -static int put_node __ARGS((FILE *fd, wordnode_T *node, int index, int regionmask, int prefixtree)); +static int put_node __ARGS((FILE *fd, wordnode_T *node, int idx, int regionmask, int prefixtree)); static void spell_make_sugfile __ARGS((spellinfo_T *spin, char_u *wfname)); static int sug_filltree __ARGS((spellinfo_T *spin, slang_T *slang)); static int sug_maketable __ARGS((spellinfo_T *spin)); @@ -5223,8 +5389,7 @@ spell_read_aff(spin, fname) /* Handle non-empty lines. */ if (itemcnt > 0) { - if (STRCMP(items[0], "SET") == 0 && itemcnt == 2 - && aff->af_enc == NULL) + if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) { #ifdef FEAT_MBYTE /* Setup for conversion from "ENC" to 'encoding'. */ @@ -5239,7 +5404,7 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Conversion in %s not supported"), fname); #endif } - else if (STRCMP(items[0], "FLAG") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "FLAG", 2) && aff->af_flagtype == AFT_CHAR) { if (STRCMP(items[1], "long") == 0) @@ -5284,69 +5449,71 @@ spell_read_aff(spin, fname) spin->si_info = p; } } - else if (STRCMP(items[0], "MIDWORD") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) { midword = getroom_save(spin, items[1]); } - else if (STRCMP(items[0], "TRY") == 0 && itemcnt == 2) + else if (is_aff_rule(items, itemcnt, "TRY", 2)) { /* ignored, we look in the tree for what chars may appear */ } /* TODO: remove "RAR" later */ - else if ((STRCMP(items[0], "RAR") == 0 - || STRCMP(items[0], "RARE") == 0) && itemcnt == 2 - && aff->af_rare == 0) + else if ((is_aff_rule(items, itemcnt, "RAR", 2) + || is_aff_rule(items, itemcnt, "RARE", 2)) + && aff->af_rare == 0) { aff->af_rare = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } /* TODO: remove "KEP" later */ - else if ((STRCMP(items[0], "KEP") == 0 - || STRCMP(items[0], "KEEPCASE") == 0) && itemcnt == 2 + else if ((is_aff_rule(items, itemcnt, "KEP", 2) + || is_aff_rule(items, itemcnt, "KEEPCASE", 2)) && aff->af_keepcase == 0) { aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "BAD") == 0 && itemcnt == 2 - && aff->af_bad == 0) + else if ((is_aff_rule(items, itemcnt, "BAD", 2) + || is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2)) + && aff->af_bad == 0) { aff->af_bad = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "NEEDAFFIX") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2) && aff->af_needaffix == 0) { aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "CIRCUMFIX") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2) && aff->af_circumfix == 0) { aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "NOSUGGEST") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2) && aff->af_nosuggest == 0) { aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "NEEDCOMPOUND") == 0 && itemcnt == 2 + else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2) + || is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2)) && aff->af_needcomp == 0) { aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "COMPOUNDROOT") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2) && aff->af_comproot == 0) { aff->af_comproot = affitem2flag(aff->af_flagtype, items[1], fname, lnum); } - else if (STRCMP(items[0], "COMPOUNDFORBIDFLAG") == 0 - && itemcnt == 2 && aff->af_compforbid == 0) + else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2) + && aff->af_compforbid == 0) { aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1], fname, lnum); @@ -5354,8 +5521,8 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"), fname, lnum); } - else if (STRCMP(items[0], "COMPOUNDPERMITFLAG") == 0 - && itemcnt == 2 && aff->af_comppermit == 0) + else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2) + && aff->af_comppermit == 0) { aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1], fname, lnum); @@ -5363,7 +5530,7 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"), fname, lnum); } - else if (STRCMP(items[0], "COMPOUNDFLAG") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2) && compflags == NULL) { /* Turn flag "c" into COMPOUNDRULE compatible string "c+", @@ -5376,7 +5543,15 @@ spell_read_aff(spin, fname) compflags = p; } } - else if (STRCMP(items[0], "COMPOUNDRULE") == 0 && itemcnt == 2) + else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) + { + /* We don't use the count, but do check that it's a number and + * not COMPOUNDRULE mistyped. */ + if (atoi((char *)items[1]) == 0) + smsg((char_u *)_("Wrong COMPOUNDRULES value in %s line %d: %s"), + fname, lnum, items[1]); + } + else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { /* Concatenate this string to previously defined ones, using a * slash to separate them. */ @@ -5395,7 +5570,7 @@ spell_read_aff(spin, fname) compflags = p; } } - else if (STRCMP(items[0], "COMPOUNDWORDMAX") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) && compmax == 0) { compmax = atoi((char *)items[1]); @@ -5403,7 +5578,7 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"), fname, lnum, items[1]); } - else if (STRCMP(items[0], "COMPOUNDMIN") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2) && compminlen == 0) { compminlen = atoi((char *)items[1]); @@ -5411,7 +5586,7 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Wrong COMPOUNDMIN value in %s line %d: %s"), fname, lnum, items[1]); } - else if (STRCMP(items[0], "COMPOUNDSYLMAX") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2) && compsylmax == 0) { compsylmax = atoi((char *)items[1]); @@ -5419,32 +5594,29 @@ spell_read_aff(spin, fname) smsg((char_u *)_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"), fname, lnum, items[1]); } - else if (STRCMP(items[0], "CHECKCOMPOUNDDUP") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1)) { compoptions |= COMP_CHECKDUP; } - else if (STRCMP(items[0], "CHECKCOMPOUNDREP") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1)) { compoptions |= COMP_CHECKREP; } - else if (STRCMP(items[0], "CHECKCOMPOUNDCASE") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1)) { compoptions |= COMP_CHECKCASE; } - else if (STRCMP(items[0], "CHECKCOMPOUNDTRIPLE") == 0 - && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1)) { compoptions |= COMP_CHECKTRIPLE; } - else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0 - && itemcnt == 2) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2)) { if (atoi((char *)items[1]) == 0) smsg((char_u *)_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"), fname, lnum, items[1]); } - else if (STRCMP(items[0], "CHECKCOMPOUNDPATTERN") == 0 - && itemcnt == 3) + else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3)) { garray_T *gap = &spin->si_comppat; int i; @@ -5463,24 +5635,24 @@ spell_read_aff(spin, fname) = getroom_save(spin, items[2]); } } - else if (STRCMP(items[0], "SYLLABLE") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2) && syllable == NULL) { syllable = getroom_save(spin, items[1]); } - else if (STRCMP(items[0], "NOBREAK") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) { spin->si_nobreak = TRUE; } - else if (STRCMP(items[0], "NOSPLITSUGS") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) { spin->si_nosplitsugs = TRUE; } - else if (STRCMP(items[0], "NOSUGFILE") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { spin->si_nosugfile = TRUE; } - else if (STRCMP(items[0], "PFXPOSTPONE") == 0 && itemcnt == 1) + else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { aff->af_pfxpostpone = TRUE; } @@ -5771,24 +5943,20 @@ spell_read_aff(spin, fname) } } } - else if (STRCMP(items[0], "FOL") == 0 && itemcnt == 2 - && fol == NULL) + else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) { fol = vim_strsave(items[1]); } - else if (STRCMP(items[0], "LOW") == 0 && itemcnt == 2 - && low == NULL) + else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) { low = vim_strsave(items[1]); } - else if (STRCMP(items[0], "UPP") == 0 && itemcnt == 2 - && upp == NULL) + else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) { upp = vim_strsave(items[1]); } - else if ((STRCMP(items[0], "REP") == 0 - || STRCMP(items[0], "REPSAL") == 0) - && itemcnt == 2) + else if (is_aff_rule(items, itemcnt, "REP", 2) + || is_aff_rule(items, itemcnt, "REPSAL", 2)) { /* Ignore REP/REPSAL count */; if (!isdigit(*items[1])) @@ -5819,7 +5987,7 @@ spell_read_aff(spin, fname) : &spin->si_rep, items[1], items[2]); } } - else if (STRCMP(items[0], "MAP") == 0 && itemcnt == 2) + else if (is_aff_rule(items, itemcnt, "MAP", 2)) { /* MAP item or count */ if (!found_map) @@ -5856,9 +6024,8 @@ spell_read_aff(spin, fname) ga_append(&spin->si_map, '/'); } } - /* Accept "SAL from to" and "SAL from to # comment". */ - else if (STRCMP(items[0], "SAL") == 0 - && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#'))) + /* Accept "SAL from to" and "SAL from to #comment". */ + else if (is_aff_rule(items, itemcnt, "SAL", 3)) { if (do_sal) { @@ -5877,12 +6044,12 @@ spell_read_aff(spin, fname) : items[2]); } } - else if (STRCMP(items[0], "SOFOFROM") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2) && sofofrom == NULL) { sofofrom = getroom_save(spin, items[1]); } - else if (STRCMP(items[0], "SOFOTO") == 0 && itemcnt == 2 + else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) && sofoto == NULL) { sofoto = getroom_save(spin, items[1]); @@ -6016,6 +6183,22 @@ spell_read_aff(spin, fname) return aff; } +/* + * Return TRUE when items[0] equals "rulename", there are "mincount" items or + * a comment is following after item "mincount". + */ + static int +is_aff_rule(items, itemcnt, rulename, mincount) + char_u **items; + int itemcnt; + char *rulename; + int mincount; +{ + return (STRCMP(items[0], rulename) == 0 + && (itemcnt == mincount + || (itemcnt > mincount && items[mincount][0] == '#'))); +} + /* * For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from * ae_flags to ae_comppermit and ae_compforbid. @@ -7926,6 +8109,8 @@ write_vim_spell(spin, fname) char_u *p; int rr; int retval = OK; + size_t fwv = 1; /* collect return value of fwrite() to avoid + warnings from picky compiler */ fd = mch_fopen((char *)fname, "w"); if (fd == NULL) @@ -7936,11 +8121,11 @@ write_vim_spell(spin, fname) /*
: */ /* */ - if (fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd) != 1) - { - EMSG(_(e_write)); - retval = FAIL; - } + fwv &= fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd); + if (fwv != (size_t)1) + /* Catch first write error, don't try writing more. */ + goto theend; + putc(VIMSPELLVERSION, fd); /* */ /* @@ -7955,7 +8140,7 @@ write_vim_spell(spin, fname) i = (int)STRLEN(spin->si_info); put_bytes(fd, (long_u)i, 4); /* */ - fwrite(spin->si_info, (size_t)i, (size_t)1, fd); /* */ + fwv &= fwrite(spin->si_info, (size_t)i, (size_t)1, fd); /* */ } /* SN_REGION: ... @@ -7966,7 +8151,7 @@ write_vim_spell(spin, fname) putc(SNF_REQUIRED, fd); /* */ l = spin->si_region_count * 2; put_bytes(fd, (long_u)l, 4); /* */ - fwrite(spin->si_region_name, (size_t)l, (size_t)1, fd); + fwv &= fwrite(spin->si_region_name, (size_t)l, (size_t)1, fd); /* ... */ regionmask = (1 << spin->si_region_count) - 1; } @@ -8016,7 +8201,7 @@ write_vim_spell(spin, fname) } put_bytes(fd, (long_u)l, 2); /* */ - fwrite(folchars, (size_t)l, (size_t)1, fd); /* */ + fwv &= fwrite(folchars, (size_t)l, (size_t)1, fd); /* */ } /* SN_MIDWORD: */ @@ -8027,7 +8212,8 @@ write_vim_spell(spin, fname) i = (int)STRLEN(spin->si_midword); put_bytes(fd, (long_u)i, 4); /* */ - fwrite(spin->si_midword, (size_t)i, (size_t)1, fd); /* */ + fwv &= fwrite(spin->si_midword, (size_t)i, (size_t)1, fd); + /* */ } /* SN_PREFCOND: ... */ @@ -8113,7 +8299,8 @@ write_vim_spell(spin, fname) p = rr == 1 ? ftp->ft_from : ftp->ft_to; l = (int)STRLEN(p); putc(l, fd); - fwrite(p, l, (size_t)1, fd); + if (l > 0) + fwv &= fwrite(p, l, (size_t)1, fd); } } @@ -8131,11 +8318,11 @@ write_vim_spell(spin, fname) /* */ put_bytes(fd, (long_u)l, 2); /* */ - fwrite(spin->si_sofofr, l, (size_t)1, fd); /* */ + fwv &= fwrite(spin->si_sofofr, l, (size_t)1, fd); /* */ l = (int)STRLEN(spin->si_sofoto); put_bytes(fd, (long_u)l, 2); /* */ - fwrite(spin->si_sofoto, l, (size_t)1, fd); /* */ + fwv &= fwrite(spin->si_sofoto, l, (size_t)1, fd); /* */ } /* SN_WORDS: ... @@ -8160,7 +8347,7 @@ write_vim_spell(spin, fname) l = (int)STRLEN(hi->hi_key) + 1; len += l; if (round == 2) /* */ - fwrite(hi->hi_key, (size_t)l, (size_t)1, fd); + fwv &= fwrite(hi->hi_key, (size_t)l, (size_t)1, fd); --todo; } if (round == 1) @@ -8176,7 +8363,7 @@ write_vim_spell(spin, fname) putc(0, fd); /* */ l = spin->si_map.ga_len; put_bytes(fd, (long_u)l, 4); /* */ - fwrite(spin->si_map.ga_data, (size_t)l, (size_t)1, fd); + fwv &= fwrite(spin->si_map.ga_data, (size_t)l, (size_t)1, fd); /* */ } @@ -8232,10 +8419,11 @@ write_vim_spell(spin, fname) { p = ((char_u **)(spin->si_comppat.ga_data))[i]; putc((int)STRLEN(p), fd); /* */ - fwrite(p, (size_t)STRLEN(p), (size_t)1, fd);/* */ + fwv &= fwrite(p, (size_t)STRLEN(p), (size_t)1, fd); + /* */ } /* */ - fwrite(spin->si_compflags, (size_t)STRLEN(spin->si_compflags), + fwv &= fwrite(spin->si_compflags, (size_t)STRLEN(spin->si_compflags), (size_t)1, fd); } @@ -8259,7 +8447,8 @@ write_vim_spell(spin, fname) l = (int)STRLEN(spin->si_syllable); put_bytes(fd, (long_u)l, 4); /* */ - fwrite(spin->si_syllable, (size_t)l, (size_t)1, fd); /* */ + fwv &= fwrite(spin->si_syllable, (size_t)l, (size_t)1, fd); + /* */ } /* end of */ @@ -8295,13 +8484,18 @@ write_vim_spell(spin, fname) (void)put_node(fd, tree, 0, regionmask, round == 3); } - /* Write another byte to check for errors. */ + /* Write another byte to check for errors (file system full). */ if (putc(0, fd) == EOF) retval = FAIL; - +theend: if (fclose(fd) == EOF) retval = FAIL; + if (fwv != (size_t)1) + retval = FAIL; + if (retval == FAIL) + EMSG(_(e_write)); + return retval; } @@ -9890,6 +10084,7 @@ write_spell_prefcond(fd, gap) char_u *p; int len; int totlen; + size_t x = 1; /* collect return value of fwrite() */ if (fd != NULL) put_bytes(fd, (long_u)gap->ga_len, 2); /* */ @@ -9906,7 +10101,7 @@ write_spell_prefcond(fd, gap) if (fd != NULL) { fputc(len, fd); - fwrite(p, (size_t)len, (size_t)1, fd); + x &= fwrite(p, (size_t)len, (size_t)1, fd); } totlen += len; } @@ -11480,15 +11675,24 @@ suggest_trie_walk(su, lp, fword, soundfold) vim_strncpy(preword + sp->ts_prewordlen, tword + sp->ts_splitoff, sp->ts_twordlen - sp->ts_splitoff); - p = preword; - while (*skiptowhite(p) != NUL) - p = skipwhite(skiptowhite(p)); - if (fword_ends && !can_compound(slang, p, - compflags + sp->ts_compsplit)) - /* Compound is not allowed. But it may still be - * possible if we add another (short) word. */ + + /* Verify CHECKCOMPOUNDPATTERN rules. */ + if (match_checkcompoundpattern(preword, sp->ts_prewordlen, + &slang->sl_comppat)) compound_ok = FALSE; + if (compound_ok) + { + p = preword; + while (*skiptowhite(p) != NUL) + p = skipwhite(skiptowhite(p)); + if (fword_ends && !can_compound(slang, p, + compflags + sp->ts_compsplit)) + /* Compound is not allowed. But it may still be + * possible if we add another (short) word. */ + compound_ok = FALSE; + } + /* Get pointer to last char of previous word. */ p = preword + sp->ts_prewordlen; mb_ptr_back(preword, p); @@ -11685,10 +11889,9 @@ suggest_trie_walk(su, lp, fword, soundfold) && (slang->sl_compsylmax < MAXWLEN || sp->ts_complen + 1 - sp->ts_compsplit < slang->sl_compmax) - && (byte_in_str(sp->ts_complen == sp->ts_compsplit - ? slang->sl_compstartflags - : slang->sl_compallflags, - ((unsigned)flags >> 24)))) + && (can_be_compound(sp, slang, + compflags, ((unsigned)flags >> 24)))) + { try_compound = TRUE; compflags[sp->ts_complen] = ((unsigned)flags >> 24); diff --git a/src/tag.c b/src/tag.c index 1352f2047a..62533f64e8 100644 --- a/src/tag.c +++ b/src/tag.c @@ -2725,7 +2725,24 @@ parse_tag_line(lbuf, */ p_7f = vim_strchr(lbuf, 0x7f); if (p_7f == NULL) + { +etag_fail: + if (vim_strchr(lbuf, '\n') == NULL) + { + /* Truncated line. Ignore it. */ + if (p_verbose >= 5) + { + verbose_enter(); + MSG(_("Ignoring long line in tags file")); + verbose_leave(); + } + tagp->command = lbuf; + tagp->tagname = lbuf; + tagp->tagname_end = lbuf; + return OK; + } return FAIL; + } /* Find ^A. If not found the line number is after the 0x7f */ p = vim_strchr(p_7f, Ctrl_A); @@ -2735,7 +2752,7 @@ parse_tag_line(lbuf, ++p; if (!VIM_ISDIGIT(*p)) /* check for start of line number */ - return FAIL; + goto etag_fail; tagp->command = p; @@ -2749,7 +2766,7 @@ parse_tag_line(lbuf, /* find end of tagname */ for (p = p_7f - 1; !vim_iswordc(*p); --p) if (p == lbuf) - return FAIL; + goto etag_fail; tagp->tagname_end = p + 1; while (p >= lbuf && vim_iswordc(*p)) --p; diff --git a/src/ui.c b/src/ui.c index dac29e2d55..b8b52d79ae 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1834,7 +1834,7 @@ fill_input_buf(exit_on_error) #ifdef HAVE_DUP /* Use stderr for stdin, also works for shell commands. */ close(0); - dup(2); + ignored = dup(2); #else read_cmd_fd = 2; /* read from stderr instead of stdin */ #endif diff --git a/src/version.c b/src/version.c index 6057bff051..1ad8d1bda5 100644 --- a/src/version.c +++ b/src/version.c @@ -691,6 +691,58 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 75, +/**/ + 74, +/**/ + 73, +/**/ + 72, +/**/ + 71, +/**/ + 70, +/**/ + 69, +/**/ + 68, +/**/ + 67, +/**/ + 66, +/**/ + 65, +/**/ + 64, +/**/ + 63, +/**/ + 62, +/**/ + 61, +/**/ + 60, +/**/ + 59, +/**/ + 58, +/**/ + 57, +/**/ + 56, +/**/ + 55, +/**/ + 54, +/**/ + 53, +/**/ + 52, +/**/ + 51, +/**/ + 50, /**/ 49, /**/ @@ -793,6 +845,19 @@ static int included_patches[] = 0 }; +/* + * Place to put a short description when adding a feature with a patch. + * Keep it short, e.g.,: "relative numbers", "persistent undo". + * Also add a comment marker to separate the lines. + * See the official Vim patches for the diff format: It must use a context of + * one line only. Create it by hand or use "diff -C2" and edit the patch. + */ +static char *(extra_patches[]) = +{ /* Add your patch description below this line */ +/**/ + NULL +}; + int highest_patch() { @@ -938,6 +1003,19 @@ list_version() } } + /* Print the list of extra patch descriptions if there is at least one. */ + if (extra_patches[0] != NULL) + { + MSG_PUTS(_("\nExtra patches: ")); + s = ""; + for (i = 0; extra_patches[i] != NULL; ++i) + { + MSG_PUTS(s); + s = ", "; + MSG_PUTS(extra_patches[i]); + } + } + #ifdef MODIFIED_BY MSG_PUTS("\n"); MSG_PUTS(_("Modified by ")); diff --git a/src/window.c b/src/window.c index 2feb9e25b5..b360f54e11 100644 --- a/src/window.c +++ b/src/window.c @@ -4029,14 +4029,14 @@ win_enter_ext(wp, undo_sync, curwin_invalid) if (mch_dirname(cwd, MAXPATHL) == OK) globaldir = vim_strsave(cwd); } - mch_chdir((char *)curwin->w_localdir); - shorten_fnames(TRUE); + if (mch_chdir((char *)curwin->w_localdir) == 0) + shorten_fnames(TRUE); } else if (globaldir != NULL) { /* Window doesn't have a local directory and we are not in the global * directory: Change to the global directory. */ - mch_chdir((char *)globaldir); + ignored = mch_chdir((char *)globaldir); vim_free(globaldir); globaldir = NULL; shorten_fnames(TRUE); diff --git a/src/workshop.c b/src/workshop.c index 66a60d3ba8..ef25b5a874 100644 --- a/src/workshop.c +++ b/src/workshop.c @@ -1121,8 +1121,12 @@ workshop_get_positions( ? (char *)curbuf->b_sfname : ""); #endif - strcpy(ffname, (char *) curbuf->b_ffname); - *filename = ffname; /* copy so nobody can change b_ffname */ + if (curbuf->b_ffname == NULL) + ffname[0] = NUL; + else + /* copy so nobody can change b_ffname */ + strcpy(ffname, (char *) curbuf->b_ffname); + *filename = ffname; *curLine = curwin->w_cursor.lnum; *curCol = curwin->w_cursor.col;