Mirror of the Vim source from https://github.com/vim/vim
修訂 | e943e5502fc9cc439294de385dc564226b7311a1 (tree) |
---|---|
時間 | 2005-02-12 23:31:42 |
作者 | vimboss |
Commiter | vimboss |
updated for version 7.0050
@@ -335,10 +335,10 @@ | ||
335 | 335 | static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); |
336 | 336 | static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef)); |
337 | 337 | static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); |
338 | -static list_T *list_copy __ARGS((list_T *orig, int deep)); | |
338 | +static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); | |
339 | 339 | static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); |
340 | 340 | static char_u *list2string __ARGS((typval_T *tv)); |
341 | -static void list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo)); | |
341 | +static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo)); | |
342 | 342 | |
343 | 343 | static dict_T *dict_alloc __ARGS((void)); |
344 | 344 | static void dict_unref __ARGS((dict_T *d)); |
@@ -347,6 +347,7 @@ | ||
347 | 347 | static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); |
348 | 348 | static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); |
349 | 349 | static void dictitem_free __ARGS((dictitem_T *item)); |
350 | +static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID)); | |
350 | 351 | static int dict_add __ARGS((dict_T *d, dictitem_T *item)); |
351 | 352 | static long dict_len __ARGS((dict_T *d)); |
352 | 353 | static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len)); |
@@ -361,6 +362,7 @@ | ||
361 | 362 | static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); |
362 | 363 | static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); |
363 | 364 | static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); |
365 | +static void emsg_funcname __ARGS((char *msg, char_u *name)); | |
364 | 366 | |
365 | 367 | static void f_add __ARGS((typval_T *argvars, typval_T *rettv)); |
366 | 368 | static void f_append __ARGS((typval_T *argvars, typval_T *rettv)); |
@@ -562,7 +564,7 @@ | ||
562 | 564 | static int var_check_ro __ARGS((int flags, char_u *name)); |
563 | 565 | static int tv_check_lock __ARGS((int lock, char_u *name)); |
564 | 566 | static void copy_tv __ARGS((typval_T *from, typval_T *to)); |
565 | -static void item_copy __ARGS((typval_T *from, typval_T *to, int deep)); | |
567 | +static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID)); | |
566 | 568 | static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags)); |
567 | 569 | static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd)); |
568 | 570 | static int eval_fname_script __ARGS((char_u *p)); |
@@ -2497,10 +2499,7 @@ | ||
2497 | 2499 | |
2498 | 2500 | if (*startarg != '(') |
2499 | 2501 | { |
2500 | - if (*name == K_SPECIAL) | |
2501 | - EMSG2(_("E107: Missing braces: <SNR>%s"), name + 3); | |
2502 | - else | |
2503 | - EMSG2(_("E107: Missing braces: %s"), name); | |
2502 | + EMSG2(_("E107: Missing braces: %s"), eap->arg); | |
2504 | 2503 | goto end; |
2505 | 2504 | } |
2506 | 2505 |
@@ -4961,7 +4960,7 @@ | ||
4961 | 4960 | list_T *l; |
4962 | 4961 | |
4963 | 4962 | /* make a copy of the first list. */ |
4964 | - l = list_copy(l1, FALSE); | |
4963 | + l = list_copy(l1, FALSE, 0); | |
4965 | 4964 | if (l == NULL) |
4966 | 4965 | return FAIL; |
4967 | 4966 | tv->v_type = VAR_LIST; |
@@ -4974,12 +4973,14 @@ | ||
4974 | 4973 | /* |
4975 | 4974 | * Make a copy of list "orig". Shallow if "deep" is FALSE. |
4976 | 4975 | * The refcount of the new list is set to 1. |
4976 | + * See item_copy() for "copyID". | |
4977 | 4977 | * Returns NULL when out of memory. |
4978 | 4978 | */ |
4979 | 4979 | static list_T * |
4980 | -list_copy(orig, deep) | |
4980 | +list_copy(orig, deep, copyID) | |
4981 | 4981 | list_T *orig; |
4982 | 4982 | int deep; |
4983 | + int copyID; | |
4983 | 4984 | { |
4984 | 4985 | list_T *copy; |
4985 | 4986 | listitem_T *item; |
@@ -4991,18 +4992,37 @@ | ||
4991 | 4992 | copy = list_alloc(); |
4992 | 4993 | if (copy != NULL) |
4993 | 4994 | { |
4994 | - for (item = orig->lv_first; item != NULL; item = item->li_next) | |
4995 | + if (copyID != 0) | |
4996 | + { | |
4997 | + /* Do this before adding the items, because one of the items may | |
4998 | + * refer back to this list. */ | |
4999 | + orig->lv_copyID = copyID; | |
5000 | + orig->lv_copylist = copy; | |
5001 | + } | |
5002 | + for (item = orig->lv_first; item != NULL && !got_int; | |
5003 | + item = item->li_next) | |
4995 | 5004 | { |
4996 | 5005 | ni = listitem_alloc(); |
4997 | 5006 | if (ni == NULL) |
4998 | 5007 | break; |
4999 | 5008 | if (deep) |
5000 | - item_copy(&item->li_tv, &ni->li_tv, deep); | |
5009 | + { | |
5010 | + if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL) | |
5011 | + { | |
5012 | + vim_free(ni); | |
5013 | + break; | |
5014 | + } | |
5015 | + } | |
5001 | 5016 | else |
5002 | 5017 | copy_tv(&item->li_tv, &ni->li_tv); |
5003 | 5018 | list_append(copy, ni); |
5004 | 5019 | } |
5005 | 5020 | ++copy->lv_refcount; |
5021 | + if (item != NULL) | |
5022 | + { | |
5023 | + list_unref(copy); | |
5024 | + copy = NULL; | |
5025 | + } | |
5006 | 5026 | } |
5007 | 5027 | |
5008 | 5028 | return copy; |
@@ -5054,7 +5074,11 @@ | ||
5054 | 5074 | return NULL; |
5055 | 5075 | ga_init2(&ga, (int)sizeof(char), 80); |
5056 | 5076 | ga_append(&ga, '['); |
5057 | - list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE); | |
5077 | + if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL) | |
5078 | + { | |
5079 | + vim_free(ga.ga_data); | |
5080 | + return NULL; | |
5081 | + } | |
5058 | 5082 | ga_append(&ga, ']'); |
5059 | 5083 | ga_append(&ga, NUL); |
5060 | 5084 | return (char_u *)ga.ga_data; |
@@ -5063,8 +5087,9 @@ | ||
5063 | 5087 | /* |
5064 | 5088 | * Join list "l" into a string in "*gap", using separator "sep". |
5065 | 5089 | * When "echo" is TRUE use String as echoed, otherwise as inside a List. |
5066 | - */ | |
5067 | - static void | |
5090 | + * Return FAIL or OK. | |
5091 | + */ | |
5092 | + static int | |
5068 | 5093 | list_join(gap, l, sep, echo) |
5069 | 5094 | garray_T *gap; |
5070 | 5095 | list_T *l; |
@@ -5077,7 +5102,7 @@ | ||
5077 | 5102 | listitem_T *item; |
5078 | 5103 | char_u *s; |
5079 | 5104 | |
5080 | - for (item = l->lv_first; item != NULL; item = item->li_next) | |
5105 | + for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) | |
5081 | 5106 | { |
5082 | 5107 | if (first) |
5083 | 5108 | first = FALSE; |
@@ -5091,7 +5116,10 @@ | ||
5091 | 5116 | if (s != NULL) |
5092 | 5117 | ga_concat(gap, s); |
5093 | 5118 | vim_free(tofree); |
5094 | - } | |
5119 | + if (s == NULL) | |
5120 | + return FAIL; | |
5121 | + } | |
5122 | + return OK; | |
5095 | 5123 | } |
5096 | 5124 | |
5097 | 5125 | /* |
@@ -5108,6 +5136,7 @@ | ||
5108 | 5136 | hash_init(&d->dv_hashtab); |
5109 | 5137 | d->dv_lock = 0; |
5110 | 5138 | d->dv_refcount = 0; |
5139 | + d->dv_copyID = 0; | |
5111 | 5140 | } |
5112 | 5141 | return d; |
5113 | 5142 | } |
@@ -5222,12 +5251,14 @@ | ||
5222 | 5251 | /* |
5223 | 5252 | * Make a copy of dict "d". Shallow if "deep" is FALSE. |
5224 | 5253 | * The refcount of the new dict is set to 1. |
5254 | + * See item_copy() for "copyID". | |
5225 | 5255 | * Returns NULL when out of memory. |
5226 | 5256 | */ |
5227 | 5257 | static dict_T * |
5228 | -dict_copy(orig, deep) | |
5258 | +dict_copy(orig, deep, copyID) | |
5229 | 5259 | dict_T *orig; |
5230 | 5260 | int deep; |
5261 | + int copyID; | |
5231 | 5262 | { |
5232 | 5263 | dict_T *copy; |
5233 | 5264 | dictitem_T *di; |
@@ -5240,8 +5271,13 @@ | ||
5240 | 5271 | copy = dict_alloc(); |
5241 | 5272 | if (copy != NULL) |
5242 | 5273 | { |
5274 | + if (copyID != 0) | |
5275 | + { | |
5276 | + orig->dv_copyID = copyID; | |
5277 | + orig->dv_copydict = copy; | |
5278 | + } | |
5243 | 5279 | todo = orig->dv_hashtab.ht_used; |
5244 | - for (hi = orig->dv_hashtab.ht_array; todo > 0; ++hi) | |
5280 | + for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) | |
5245 | 5281 | { |
5246 | 5282 | if (!HASHITEM_EMPTY(hi)) |
5247 | 5283 | { |
@@ -5251,7 +5287,14 @@ | ||
5251 | 5287 | if (di == NULL) |
5252 | 5288 | break; |
5253 | 5289 | if (deep) |
5254 | - item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep); | |
5290 | + { | |
5291 | + if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep, | |
5292 | + copyID) == FAIL) | |
5293 | + { | |
5294 | + vim_free(di); | |
5295 | + break; | |
5296 | + } | |
5297 | + } | |
5255 | 5298 | else |
5256 | 5299 | copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); |
5257 | 5300 | if (dict_add(copy, di) == FAIL) |
@@ -5263,6 +5306,11 @@ | ||
5263 | 5306 | } |
5264 | 5307 | |
5265 | 5308 | ++copy->dv_refcount; |
5309 | + if (todo > 0) | |
5310 | + { | |
5311 | + dict_unref(copy); | |
5312 | + copy = NULL; | |
5313 | + } | |
5266 | 5314 | } |
5267 | 5315 | |
5268 | 5316 | return copy; |
@@ -5355,7 +5403,7 @@ | ||
5355 | 5403 | ga_append(&ga, '{'); |
5356 | 5404 | |
5357 | 5405 | todo = d->dv_hashtab.ht_used; |
5358 | - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) | |
5406 | + for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) | |
5359 | 5407 | { |
5360 | 5408 | if (!HASHITEM_EMPTY(hi)) |
5361 | 5409 | { |
@@ -5377,7 +5425,14 @@ | ||
5377 | 5425 | if (s != NULL) |
5378 | 5426 | ga_concat(&ga, s); |
5379 | 5427 | vim_free(tofree); |
5380 | - } | |
5428 | + if (s == NULL) | |
5429 | + break; | |
5430 | + } | |
5431 | + } | |
5432 | + if (todo > 0) | |
5433 | + { | |
5434 | + vim_free(ga.ga_data); | |
5435 | + return NULL; | |
5381 | 5436 | } |
5382 | 5437 | |
5383 | 5438 | ga_append(&ga, '}'); |
@@ -5721,7 +5776,7 @@ | ||
5721 | 5776 | {"count", 2, 4, f_count}, |
5722 | 5777 | {"cscope_connection",0,3, f_cscope_connection}, |
5723 | 5778 | {"cursor", 2, 2, f_cursor}, |
5724 | - {"deepcopy", 1, 1, f_deepcopy}, | |
5779 | + {"deepcopy", 1, 2, f_deepcopy}, | |
5725 | 5780 | {"delete", 1, 1, f_delete}, |
5726 | 5781 | {"did_filetype", 0, 0, f_did_filetype}, |
5727 | 5782 | {"diff_filler", 1, 1, f_diff_filler}, |
@@ -6043,9 +6098,9 @@ | ||
6043 | 6098 | else if (!aborting()) |
6044 | 6099 | { |
6045 | 6100 | if (argcount == MAX_FUNC_ARGS) |
6046 | - EMSG2(_("E740: Too many arguments for function %s"), name); | |
6047 | - else | |
6048 | - EMSG2(_("E116: Invalid arguments for function %s"), name); | |
6101 | + emsg_funcname("E740: Too many arguments for function %s", name); | |
6102 | + else | |
6103 | + emsg_funcname("E116: Invalid arguments for function %s", name); | |
6049 | 6104 | } |
6050 | 6105 | |
6051 | 6106 | while (--argcount >= 0) |
@@ -6247,21 +6302,21 @@ | ||
6247 | 6302 | switch (error) |
6248 | 6303 | { |
6249 | 6304 | case ERROR_UNKNOWN: |
6250 | - EMSG2(_("E117: Unknown function: %s"), name); | |
6305 | + emsg_funcname("E117: Unknown function: %s", name); | |
6251 | 6306 | break; |
6252 | 6307 | case ERROR_TOOMANY: |
6253 | - EMSG2(_(e_toomanyarg), name); | |
6308 | + emsg_funcname(e_toomanyarg, name); | |
6254 | 6309 | break; |
6255 | 6310 | case ERROR_TOOFEW: |
6256 | - EMSG2(_("E119: Not enough arguments for function: %s"), | |
6311 | + emsg_funcname("E119: Not enough arguments for function: %s", | |
6257 | 6312 | name); |
6258 | 6313 | break; |
6259 | 6314 | case ERROR_SCRIPT: |
6260 | - EMSG2(_("E120: Using <SID> not in a script context: %s"), | |
6315 | + emsg_funcname("E120: Using <SID> not in a script context: %s", | |
6261 | 6316 | name); |
6262 | 6317 | break; |
6263 | 6318 | case ERROR_DICT: |
6264 | - EMSG2(_("E725: Calling dict function without Dictionary: %s"), | |
6319 | + emsg_funcname("E725: Calling dict function without Dictionary: %s", | |
6265 | 6320 | name); |
6266 | 6321 | break; |
6267 | 6322 | } |
@@ -6274,6 +6329,25 @@ | ||
6274 | 6329 | return ret; |
6275 | 6330 | } |
6276 | 6331 | |
6332 | +/* | |
6333 | + * Give an error message with a function name. Handle <SNR> things. | |
6334 | + */ | |
6335 | + static void | |
6336 | +emsg_funcname(msg, name) | |
6337 | + char *msg; | |
6338 | + char_u *name; | |
6339 | +{ | |
6340 | + char_u *p; | |
6341 | + | |
6342 | + if (*name == K_SPECIAL) | |
6343 | + p = concat_str((char_u *)"<SNR>", name + 3); | |
6344 | + else | |
6345 | + p = name; | |
6346 | + EMSG2(_(msg), p); | |
6347 | + if (p != name) | |
6348 | + vim_free(p); | |
6349 | +} | |
6350 | + | |
6277 | 6351 | /********************************************* |
6278 | 6352 | * Implementation of the built-in functions |
6279 | 6353 | */ |
@@ -6906,7 +6980,7 @@ | ||
6906 | 6980 | typval_T *argvars; |
6907 | 6981 | typval_T *rettv; |
6908 | 6982 | { |
6909 | - item_copy(&argvars[0], rettv, FALSE); | |
6983 | + item_copy(&argvars[0], rettv, FALSE, 0); | |
6910 | 6984 | } |
6911 | 6985 | |
6912 | 6986 | /* |
@@ -7052,7 +7126,15 @@ | ||
7052 | 7126 | typval_T *argvars; |
7053 | 7127 | typval_T *rettv; |
7054 | 7128 | { |
7055 | - item_copy(&argvars[0], rettv, TRUE); | |
7129 | + static int copyID = 0; | |
7130 | + int noref = 0; | |
7131 | + | |
7132 | + if (argvars[1].v_type != VAR_UNKNOWN) | |
7133 | + noref = get_tv_number(&argvars[1]); | |
7134 | + if (noref < 0 || noref > 1) | |
7135 | + EMSG(_(e_invarg)); | |
7136 | + else | |
7137 | + item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++copyID : 0); | |
7056 | 7138 | } |
7057 | 7139 | |
7058 | 7140 | /* |
@@ -10200,7 +10282,7 @@ | ||
10200 | 10282 | char_u *save_cpo; |
10201 | 10283 | long start = 0; |
10202 | 10284 | long nth = 1; |
10203 | - int match; | |
10285 | + int match = 0; | |
10204 | 10286 | list_T *l = NULL; |
10205 | 10287 | listitem_T *li = NULL; |
10206 | 10288 | long idx = 0; |
@@ -10275,6 +10357,8 @@ | ||
10275 | 10357 | } |
10276 | 10358 | vim_free(tofree); |
10277 | 10359 | str = echo_string(&li->li_tv, &tofree, strbuf); |
10360 | + if (str == NULL) | |
10361 | + break; | |
10278 | 10362 | } |
10279 | 10363 | |
10280 | 10364 | match = vim_regexec_nl(®match, str, (colnr_T)0); |
@@ -11394,7 +11478,7 @@ | ||
11394 | 11478 | && !tv_check_lock(l->lv_lock, (char_u *)"reverse()")) |
11395 | 11479 | { |
11396 | 11480 | li = l->lv_last; |
11397 | - l->lv_first = l->lv_last = li; | |
11481 | + l->lv_first = l->lv_last = NULL; | |
11398 | 11482 | l->lv_len = 0; |
11399 | 11483 | while (li != NULL) |
11400 | 11484 | { |
@@ -14338,7 +14422,8 @@ | ||
14338 | 14422 | } |
14339 | 14423 | if (function_exists(name)) |
14340 | 14424 | { |
14341 | - EMSG2(_("705: Variable name conflicts with existing function: %s"), name); | |
14425 | + EMSG2(_("705: Variable name conflicts with existing function: %s"), | |
14426 | + name); | |
14342 | 14427 | return; |
14343 | 14428 | } |
14344 | 14429 | } |
@@ -14520,19 +14605,24 @@ | ||
14520 | 14605 | /* |
14521 | 14606 | * Make a copy of an item. |
14522 | 14607 | * Lists and Dictionaries are also copied. A deep copy if "deep" is set. |
14523 | - */ | |
14524 | - static void | |
14525 | -item_copy(from, to, deep) | |
14608 | + * For deepcopy() "copyID" is zero for a full copy or the ID for when a | |
14609 | + * reference to an already copied list/dict can be used. | |
14610 | + * Returns FAIL or OK. | |
14611 | + */ | |
14612 | + static int | |
14613 | +item_copy(from, to, deep, copyID) | |
14526 | 14614 | typval_T *from; |
14527 | 14615 | typval_T *to; |
14528 | 14616 | int deep; |
14617 | + int copyID; | |
14529 | 14618 | { |
14530 | 14619 | static int recurse = 0; |
14620 | + int ret = OK; | |
14531 | 14621 | |
14532 | 14622 | if (recurse >= DICT_MAXNEST) |
14533 | 14623 | { |
14534 | 14624 | EMSG(_("E698: variable nested too deep for making a copy")); |
14535 | - return; | |
14625 | + return FAIL; | |
14536 | 14626 | } |
14537 | 14627 | ++recurse; |
14538 | 14628 |
@@ -14546,17 +14636,41 @@ | ||
14546 | 14636 | case VAR_LIST: |
14547 | 14637 | to->v_type = VAR_LIST; |
14548 | 14638 | to->v_lock = 0; |
14549 | - to->vval.v_list = list_copy(from->vval.v_list, deep); | |
14639 | + if (from->vval.v_list == NULL) | |
14640 | + to->vval.v_list = NULL; | |
14641 | + else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID) | |
14642 | + { | |
14643 | + /* use the copy made earlier */ | |
14644 | + to->vval.v_list = from->vval.v_list->lv_copylist; | |
14645 | + ++to->vval.v_list->lv_refcount; | |
14646 | + } | |
14647 | + else | |
14648 | + to->vval.v_list = list_copy(from->vval.v_list, deep, copyID); | |
14649 | + if (to->vval.v_list == NULL) | |
14650 | + ret = FAIL; | |
14550 | 14651 | break; |
14551 | 14652 | case VAR_DICT: |
14552 | 14653 | to->v_type = VAR_DICT; |
14553 | 14654 | to->v_lock = 0; |
14554 | - to->vval.v_dict = dict_copy(from->vval.v_dict, deep); | |
14655 | + if (from->vval.v_dict == NULL) | |
14656 | + to->vval.v_dict = NULL; | |
14657 | + else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID) | |
14658 | + { | |
14659 | + /* use the copy made earlier */ | |
14660 | + to->vval.v_dict = from->vval.v_dict->dv_copydict; | |
14661 | + ++to->vval.v_dict->dv_refcount; | |
14662 | + } | |
14663 | + else | |
14664 | + to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID); | |
14665 | + if (to->vval.v_dict == NULL) | |
14666 | + ret = FAIL; | |
14555 | 14667 | break; |
14556 | 14668 | default: |
14557 | 14669 | EMSG2(_(e_intern2), "item_copy()"); |
14670 | + ret = FAIL; | |
14558 | 14671 | } |
14559 | 14672 | --recurse; |
14673 | + return ret; | |
14560 | 14674 | } |
14561 | 14675 | |
14562 | 14676 | /* |
@@ -14604,31 +14718,34 @@ | ||
14604 | 14718 | } |
14605 | 14719 | else if (eap->cmdidx == CMD_echo) |
14606 | 14720 | msg_puts_attr((char_u *)" ", echo_attr); |
14607 | - for (p = echo_string(&rettv, &tofree, numbuf); | |
14608 | - *p != NUL && !got_int; ++p) | |
14609 | - if (*p == '\n' || *p == '\r' || *p == TAB) | |
14610 | - { | |
14611 | - if (*p != TAB && needclr) | |
14721 | + p = echo_string(&rettv, &tofree, numbuf); | |
14722 | + if (p != NULL) | |
14723 | + for ( ; *p != NUL && !got_int; ++p) | |
14724 | + { | |
14725 | + if (*p == '\n' || *p == '\r' || *p == TAB) | |
14612 | 14726 | { |
14613 | - /* remove any text still there from the command */ | |
14614 | - msg_clr_eos(); | |
14615 | - needclr = FALSE; | |
14616 | - } | |
14617 | - msg_putchar_attr(*p, echo_attr); | |
14618 | - } | |
14619 | - else | |
14620 | - { | |
14621 | -#ifdef FEAT_MBYTE | |
14622 | - if (has_mbyte) | |
14623 | - { | |
14624 | - int i = (*mb_ptr2len_check)(p); | |
14625 | - | |
14626 | - (void)msg_outtrans_len_attr(p, i, echo_attr); | |
14627 | - p += i - 1; | |
14727 | + if (*p != TAB && needclr) | |
14728 | + { | |
14729 | + /* remove any text still there from the command */ | |
14730 | + msg_clr_eos(); | |
14731 | + needclr = FALSE; | |
14732 | + } | |
14733 | + msg_putchar_attr(*p, echo_attr); | |
14628 | 14734 | } |
14629 | 14735 | else |
14630 | -#endif | |
14631 | - (void)msg_outtrans_len_attr(p, 1, echo_attr); | |
14736 | + { | |
14737 | +#ifdef FEAT_MBYTE | |
14738 | + if (has_mbyte) | |
14739 | + { | |
14740 | + int i = (*mb_ptr2len_check)(p); | |
14741 | + | |
14742 | + (void)msg_outtrans_len_attr(p, i, echo_attr); | |
14743 | + p += i - 1; | |
14744 | + } | |
14745 | + else | |
14746 | +#endif | |
14747 | + (void)msg_outtrans_len_attr(p, 1, echo_attr); | |
14748 | + } | |
14632 | 14749 | } |
14633 | 14750 | vim_free(tofree); |
14634 | 14751 | } |
@@ -14906,7 +15023,7 @@ | ||
14906 | 15023 | } |
14907 | 15024 | } |
14908 | 15025 | else |
14909 | - EMSG2(_("E123: Undefined function: %s"), name); | |
15026 | + emsg_funcname("E123: Undefined function: %s", name); | |
14910 | 15027 | } |
14911 | 15028 | goto ret_free; |
14912 | 15029 | } |
@@ -15019,7 +15136,7 @@ | ||
15019 | 15136 | if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) |
15020 | 15137 | EMSG(_(e_funcdict)); |
15021 | 15138 | else if (name != NULL && find_func(name) != NULL) |
15022 | - EMSG2(_(e_funcexts), name); | |
15139 | + emsg_funcname(e_funcexts, name); | |
15023 | 15140 | } |
15024 | 15141 | |
15025 | 15142 | msg_putchar('\n'); /* don't overwrite the function name */ |
@@ -15146,7 +15263,8 @@ | ||
15146 | 15263 | v = find_var(name, NULL); |
15147 | 15264 | if (v != NULL && v->di_tv.v_type == VAR_FUNC) |
15148 | 15265 | { |
15149 | - EMSG2(_("E707: Function name conflicts with variable: %s"), name); | |
15266 | + emsg_funcname("E707: Function name conflicts with variable: %s", | |
15267 | + name); | |
15150 | 15268 | goto erret; |
15151 | 15269 | } |
15152 | 15270 |
@@ -15155,12 +15273,12 @@ | ||
15155 | 15273 | { |
15156 | 15274 | if (!eap->forceit) |
15157 | 15275 | { |
15158 | - EMSG2(_(e_funcexts), name); | |
15276 | + emsg_funcname(e_funcexts, name); | |
15159 | 15277 | goto erret; |
15160 | 15278 | } |
15161 | 15279 | if (fp->calls > 0) |
15162 | 15280 | { |
15163 | - EMSG2(_("E127: Cannot redefine function %s: It is in use"), | |
15281 | + emsg_funcname("E127: Cannot redefine function %s: It is in use", | |
15164 | 15282 | name); |
15165 | 15283 | goto erret; |
15166 | 15284 | } |
@@ -16192,14 +16310,14 @@ | ||
16192 | 16310 | get_return_cmd(rettv) |
16193 | 16311 | void *rettv; |
16194 | 16312 | { |
16195 | - char_u *s; | |
16313 | + char_u *s = NULL; | |
16196 | 16314 | char_u *tofree = NULL; |
16197 | 16315 | char_u numbuf[NUMBUFLEN]; |
16198 | 16316 | |
16199 | - if (rettv == NULL) | |
16317 | + if (rettv != NULL) | |
16318 | + s = echo_string((typval_T *)rettv, &tofree, numbuf); | |
16319 | + if (s == NULL) | |
16200 | 16320 | s = (char_u *)""; |
16201 | - else | |
16202 | - s = echo_string((typval_T *)rettv, &tofree, numbuf); | |
16203 | 16321 | |
16204 | 16322 | STRCPY(IObuff, ":return "); |
16205 | 16323 | STRNCPY(IObuff + 8, s, IOSIZE - 8); |
@@ -16368,6 +16486,7 @@ | ||
16368 | 16486 | dictitem_T *this_var; |
16369 | 16487 | int todo; |
16370 | 16488 | char *s; |
16489 | + char_u *p; | |
16371 | 16490 | char_u *tofree; |
16372 | 16491 | char_u numbuf[NUMBUFLEN]; |
16373 | 16492 |
@@ -16392,8 +16511,9 @@ | ||
16392 | 16511 | default: continue; |
16393 | 16512 | } |
16394 | 16513 | fprintf(fp, "!%s\t%s\t", this_var->di_key, s); |
16395 | - viminfo_writestring(fp, echo_string(&this_var->di_tv, | |
16396 | - &tofree, numbuf)); | |
16514 | + p = echo_string(&this_var->di_tv, &tofree, numbuf); | |
16515 | + if (p != NULL) | |
16516 | + viminfo_writestring(fp, p); | |
16397 | 16517 | vim_free(tofree); |
16398 | 16518 | } |
16399 | 16519 | } |
@@ -3250,32 +3250,57 @@ | ||
3250 | 3250 | char_u *theline; |
3251 | 3251 | int did_undo = FALSE; |
3252 | 3252 | linenr_T lnum = eap->line2; |
3253 | + int indent = 0; | |
3254 | + char_u *p; | |
3255 | + int vcol; | |
3256 | + int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); | |
3253 | 3257 | |
3254 | 3258 | if (eap->cmdidx != CMD_append) |
3255 | 3259 | --lnum; |
3256 | 3260 | |
3261 | + /* when the buffer is empty append to line 0 and delete the dummy line */ | |
3262 | + if (empty && lnum == 1) | |
3263 | + lnum = 0; | |
3264 | + | |
3257 | 3265 | State = INSERT; /* behave like in Insert mode */ |
3258 | 3266 | if (curbuf->b_p_iminsert == B_IMODE_LMAP) |
3259 | 3267 | State |= LANGMAP; |
3268 | + | |
3260 | 3269 | while (1) |
3261 | 3270 | { |
3262 | 3271 | msg_scroll = TRUE; |
3263 | 3272 | need_wait_return = FALSE; |
3273 | + if (curbuf->b_p_ai && lnum > 0) | |
3274 | + indent = get_indent_lnum(lnum); | |
3264 | 3275 | if (eap->getline == NULL) |
3265 | 3276 | theline = getcmdline( |
3266 | 3277 | #ifdef FEAT_EVAL |
3267 | 3278 | eap->cstack->cs_looplevel > 0 ? -1 : |
3268 | 3279 | #endif |
3269 | - NUL, 0L, 0); | |
3280 | + NUL, 0L, indent); | |
3270 | 3281 | else |
3271 | 3282 | theline = eap->getline( |
3272 | 3283 | #ifdef FEAT_EVAL |
3273 | 3284 | eap->cstack->cs_looplevel > 0 ? -1 : |
3274 | 3285 | #endif |
3275 | - NUL, eap->cookie, 0); | |
3286 | + NUL, eap->cookie, indent); | |
3276 | 3287 | lines_left = Rows - 1; |
3277 | - if (theline == NULL || (theline[0] == '.' && theline[1] == NUL) | |
3278 | - || (!did_undo && u_save(lnum, lnum + 1) == FAIL)) | |
3288 | + if (theline == NULL) | |
3289 | + break; | |
3290 | + | |
3291 | + /* Look for the "." after automatic indent. */ | |
3292 | + vcol = 0; | |
3293 | + for (p = theline; indent > vcol; ++p) | |
3294 | + { | |
3295 | + if (*p == ' ') | |
3296 | + ++vcol; | |
3297 | + else if (*p == TAB) | |
3298 | + vcol += 8 - vcol % 8; | |
3299 | + else | |
3300 | + break; | |
3301 | + } | |
3302 | + if ((p[0] == '.' && p[1] == NUL) | |
3303 | + || (!did_undo && u_save(lnum, lnum + 1) == FAIL)) | |
3279 | 3304 | { |
3280 | 3305 | vim_free(theline); |
3281 | 3306 | break; |
@@ -3288,6 +3313,12 @@ | ||
3288 | 3313 | vim_free(theline); |
3289 | 3314 | ++lnum; |
3290 | 3315 | msg_didout = TRUE; /* also scroll for empty line */ |
3316 | + | |
3317 | + if (empty) | |
3318 | + { | |
3319 | + ml_delete(2L, FALSE); | |
3320 | + empty = FALSE; | |
3321 | + } | |
3291 | 3322 | } |
3292 | 3323 | State = NORMAL; |
3293 | 3324 |
@@ -3341,14 +3372,22 @@ | ||
3341 | 3372 | exarg_T *eap; |
3342 | 3373 | { |
3343 | 3374 | char_u *x; |
3344 | - int bigness = curwin->w_height - 3; | |
3345 | - char_u kind; | |
3375 | + int bigness; | |
3376 | + char_u *kind; | |
3346 | 3377 | int numbered = FALSE; |
3347 | 3378 | int minus = 0; |
3348 | 3379 | linenr_T start, end, curs, i; |
3349 | 3380 | int j; |
3350 | 3381 | linenr_T lnum = eap->line2; |
3351 | 3382 | |
3383 | + /* Vi compatible: ":z!" uses display height, without a count uses | |
3384 | + * 'scroll' */ | |
3385 | + if (eap->forceit) | |
3386 | + bigness = curwin->w_height; | |
3387 | + else if (firstwin == lastwin) | |
3388 | + bigness = curwin->w_p_scr * 2; | |
3389 | + else | |
3390 | + bigness = curwin->w_height - 3; | |
3352 | 3391 | if (bigness < 1) |
3353 | 3392 | bigness = 1; |
3354 | 3393 |
@@ -3359,8 +3398,11 @@ | ||
3359 | 3398 | ++x; |
3360 | 3399 | } |
3361 | 3400 | |
3362 | - kind = *x; | |
3363 | - if (kind == '-' || kind == '+' || kind == '=' || kind == '^' || kind == '.') | |
3401 | + kind = x; | |
3402 | + if (*kind == '-' || *kind == '+' || *kind == '=' | |
3403 | + || *kind == '^' || *kind == '.') | |
3404 | + ++x; | |
3405 | + while (*x == '-' || *x == '+') | |
3364 | 3406 | ++x; |
3365 | 3407 | |
3366 | 3408 | if (*x != 0) |
@@ -3371,15 +3413,23 @@ | ||
3371 | 3413 | return; |
3372 | 3414 | } |
3373 | 3415 | else |
3416 | + { | |
3374 | 3417 | bigness = atoi((char *)x); |
3418 | + p_window = bigness; | |
3419 | + } | |
3375 | 3420 | } |
3376 | 3421 | |
3377 | - switch (kind) | |
3422 | + /* the number of '-' and '+' multiplies the distance */ | |
3423 | + if (*kind == '-' || *kind == '+') | |
3424 | + for (x = kind + 1; *x == *kind; ++x) | |
3425 | + ; | |
3426 | + | |
3427 | + switch (*kind) | |
3378 | 3428 | { |
3379 | 3429 | case '-': |
3380 | - start = lnum - bigness; | |
3381 | - end = lnum; | |
3382 | - curs = lnum; | |
3430 | + start = lnum - bigness * (x - kind); | |
3431 | + end = start + bigness; | |
3432 | + curs = end; | |
3383 | 3433 | break; |
3384 | 3434 | |
3385 | 3435 | case '=': |
@@ -3403,7 +3453,9 @@ | ||
3403 | 3453 | |
3404 | 3454 | default: /* '+' */ |
3405 | 3455 | start = lnum; |
3406 | - end = lnum + bigness; | |
3456 | + if (*kind == '+') | |
3457 | + start += bigness * (x - kind - 1); | |
3458 | + end = start + bigness; | |
3407 | 3459 | curs = end; |
3408 | 3460 | break; |
3409 | 3461 | } |
@@ -3526,15 +3578,15 @@ | ||
3526 | 3578 | int which_pat; |
3527 | 3579 | char_u *cmd; |
3528 | 3580 | int save_State; |
3529 | - linenr_T first_line = 0; /* first changed line */ | |
3530 | - linenr_T last_line= 0; /* below last changed line AFTER the | |
3581 | + linenr_T first_line = 0; /* first changed line */ | |
3582 | + linenr_T last_line= 0; /* below last changed line AFTER the | |
3531 | 3583 | * change */ |
3532 | 3584 | linenr_T old_line_count = curbuf->b_ml.ml_line_count; |
3533 | 3585 | linenr_T line2; |
3534 | - long nmatch; /* number of lines in match */ | |
3535 | - linenr_T sub_firstlnum; /* nr of first sub line */ | |
3536 | - char_u *sub_firstline; /* allocated copy of first sub line */ | |
3537 | - int endcolumn; /* put cursor in last column when done */ | |
3586 | + long nmatch; /* number of lines in match */ | |
3587 | + linenr_T sub_firstlnum; /* nr of first sub line */ | |
3588 | + char_u *sub_firstline; /* allocated copy of first sub line */ | |
3589 | + int endcolumn = FALSE; /* cursor in last column when done */ | |
3538 | 3590 | |
3539 | 3591 | cmd = eap->arg; |
3540 | 3592 | if (!global_busy) |
@@ -609,6 +609,7 @@ | ||
609 | 609 | * Close all existing memlines and memfiles. |
610 | 610 | * Only used when exiting. |
611 | 611 | * When 'del_file' is TRUE, delete the memfiles. |
612 | + * But don't delete files that were ":preserve"d when we are POSIX compatible. | |
612 | 613 | */ |
613 | 614 | void |
614 | 615 | ml_close_all(del_file) |
@@ -617,7 +618,8 @@ | ||
617 | 618 | buf_T *buf; |
618 | 619 | |
619 | 620 | for (buf = firstbuf; buf != NULL; buf = buf->b_next) |
620 | - ml_close(buf, del_file); | |
621 | + ml_close(buf, del_file && ((buf->b_flags & BF_PRESERVED) == 0 | |
622 | + || vim_strchr(p_cpo, CPO_PRESERVE) == NULL)); | |
621 | 623 | #ifdef TEMPDIRNAMES |
622 | 624 | vim_deltempdir(); /* delete created temp directory */ |
623 | 625 | #endif |