diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-09-02 19:45:19 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-09-02 19:45:19 +0200 |
commit | b31cf2bb0be95d106bd8eef93cc07550591c1d0d (patch) | |
tree | 21fe60ccae6ed5e12c50c564ad824d0d1a746742 /src/evalfunc.c | |
parent | cf4b00c856ef714482d8d060332ac9a4d74e6b88 (diff) | |
download | vim-b31cf2bb0be95d106bd8eef93cc07550591c1d0d.zip |
patch 8.0.1039: cannot change a line in not current buffer
Problem: Cannot change a line in a buffer other than the current one.
Solution: Add setbufline(). (Yasuhiro Matsumoto, Ozaki Kiichi, closes #1953)
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r-- | src/evalfunc.c | 178 |
1 files changed, 113 insertions, 65 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 1cdb6b682..626af7c50 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -328,6 +328,7 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv); static void f_searchpos(typval_T *argvars, typval_T *rettv); static void f_server2client(typval_T *argvars, typval_T *rettv); static void f_serverlist(typval_T *argvars, typval_T *rettv); +static void f_setbufline(typval_T *argvars, typval_T *rettv); static void f_setbufvar(typval_T *argvars, typval_T *rettv); static void f_setcharsearch(typval_T *argvars, typval_T *rettv); static void f_setcmdpos(typval_T *argvars, typval_T *rettv); @@ -764,6 +765,7 @@ static struct fst {"searchpos", 1, 4, f_searchpos}, {"server2client", 2, 2, f_server2client}, {"serverlist", 0, 0, f_serverlist}, + {"setbufline", 3, 3, f_setbufline}, {"setbufvar", 3, 3, f_setbufvar}, {"setcharsearch", 1, 1, f_setcharsearch}, {"setcmdpos", 1, 1, f_setcmdpos}, @@ -9868,6 +9870,115 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv) } /* + * Set line or list of lines in buffer "buf". + */ + static void +set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines, typval_T *rettv) +{ + char_u *line = NULL; + list_T *l = NULL; + listitem_T *li = NULL; + long added = 0; + linenr_T lcount; + buf_T *curbuf_save; + int is_curbuf = buf == curbuf; + + if (buf == NULL || buf->b_ml.ml_mfp == NULL || lnum < 1) + { + rettv->vval.v_number = 1; /* FAIL */ + return; + } + + curbuf_save = curbuf; + curbuf = buf; + + lcount = curbuf->b_ml.ml_line_count; + + if (lines->v_type == VAR_LIST) + { + l = lines->vval.v_list; + li = l->lv_first; + } + else + line = get_tv_string_chk(lines); + + /* default result is zero == OK */ + for (;;) + { + if (l != NULL) + { + /* list argument, get next string */ + if (li == NULL) + break; + line = get_tv_string_chk(&li->li_tv); + li = li->li_next; + } + + rettv->vval.v_number = 1; /* FAIL */ + if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) + break; + + /* When coming here from Insert mode, sync undo, so that this can be + * undone separately from what was previously inserted. */ + if (u_sync_once == 2) + { + u_sync_once = 1; /* notify that u_sync() was called */ + u_sync(TRUE); + } + + if (lnum <= curbuf->b_ml.ml_line_count) + { + /* existing line, replace it */ + if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) + { + changed_bytes(lnum, 0); + if (is_curbuf && lnum == curwin->w_cursor.lnum) + check_cursor_col(); + rettv->vval.v_number = 0; /* OK */ + } + } + else if (added > 0 || u_save(lnum - 1, lnum) == OK) + { + /* lnum is one past the last line, append the line */ + ++added; + if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) + rettv->vval.v_number = 0; /* OK */ + } + + if (l == NULL) /* only one string argument */ + break; + ++lnum; + } + + if (added > 0) + appended_lines_mark(lcount, added); + + curbuf = curbuf_save; +} + +/* + * "setbufline()" function + */ + static void +f_setbufline(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + linenr_T lnum; + buf_T *buf; + + buf = get_buf_tv(&argvars[0], FALSE); + if (buf == NULL) + rettv->vval.v_number = 1; /* FAIL */ + else + { + lnum = get_tv_lnum_buf(&argvars[1], buf); + + set_buffer_lines(buf, lnum, &argvars[2], rettv); + } +} + +/* * "setbufvar()" function */ static void @@ -10021,72 +10132,9 @@ f_setfperm(typval_T *argvars, typval_T *rettv) static void f_setline(typval_T *argvars, typval_T *rettv) { - linenr_T lnum; - char_u *line = NULL; - list_T *l = NULL; - listitem_T *li = NULL; - long added = 0; - linenr_T lcount = curbuf->b_ml.ml_line_count; - - lnum = get_tv_lnum(&argvars[0]); - if (argvars[1].v_type == VAR_LIST) - { - l = argvars[1].vval.v_list; - li = l->lv_first; - } - else - line = get_tv_string_chk(&argvars[1]); - - /* default result is zero == OK */ - for (;;) - { - if (l != NULL) - { - /* list argument, get next string */ - if (li == NULL) - break; - line = get_tv_string_chk(&li->li_tv); - li = li->li_next; - } + linenr_T lnum = get_tv_lnum(&argvars[0]); - rettv->vval.v_number = 1; /* FAIL */ - if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) - break; - - /* When coming here from Insert mode, sync undo, so that this can be - * undone separately from what was previously inserted. */ - if (u_sync_once == 2) - { - u_sync_once = 1; /* notify that u_sync() was called */ - u_sync(TRUE); - } - - if (lnum <= curbuf->b_ml.ml_line_count) - { - /* existing line, replace it */ - if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) - { - changed_bytes(lnum, 0); - if (lnum == curwin->w_cursor.lnum) - check_cursor_col(); - rettv->vval.v_number = 0; /* OK */ - } - } - else if (added > 0 || u_save(lnum - 1, lnum) == OK) - { - /* lnum is one past the last line, append the line */ - ++added; - if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) - rettv->vval.v_number = 0; /* OK */ - } - - if (l == NULL) /* only one string argument */ - break; - ++lnum; - } - - if (added > 0) - appended_lines_mark(lcount, added); + set_buffer_lines(curbuf, lnum, &argvars[1], rettv); } static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv); |