summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-09-07 15:45:32 +0200
committerBram Moolenaar <Bram@vim.org>2019-09-07 15:45:32 +0200
commit261f346f8154c0ec7094a4a211c653c74e9f7c2e (patch)
treeae8f30b11e3a637d1c69bac234d0edd721d4a542
parenta3a124627d2eb9d36e3dc3757429d87e041f8c0b (diff)
patch 8.1.2001: some source files are too bigv8.1.2001
Problem: Some source files are too big. Solution: Move buffer and window related functions to evalbuffer.c and evalwindow.c. (Yegappan Lakshmanan, closes #4898)
-rw-r--r--Filelist4
-rw-r--r--src/Make_cyg_ming.mak2
-rw-r--r--src/Make_morph.mak2
-rw-r--r--src/Make_mvc.mak8
-rw-r--r--src/Make_vms.mms17
-rw-r--r--src/Makefile20
-rw-r--r--src/README.md2
-rw-r--r--src/buffer.c105
-rw-r--r--src/channel.c6
-rw-r--r--src/evalbuffer.c887
-rw-r--r--src/evalfunc.c1409
-rw-r--r--src/evalwindow.c1054
-rw-r--r--src/proto.h4
-rw-r--r--src/proto/buffer.pro3
-rw-r--r--src/proto/evalbuffer.pro26
-rw-r--r--src/proto/evalfunc.pro2
-rw-r--r--src/proto/evalwindow.pro36
-rw-r--r--src/proto/window.pro17
-rw-r--r--src/version.c2
-rw-r--r--src/window.c447
20 files changed, 2067 insertions, 1986 deletions
diff --git a/Filelist b/Filelist
index d67e2a25d6..d709311981 100644
--- a/Filelist
+++ b/Filelist
@@ -34,8 +34,10 @@ SRC_ALL = \
src/digraph.c \
src/edit.c \
src/eval.c \
+ src/evalbuffer.c \
src/evalfunc.c \
src/evalvars.c \
+ src/evalwindow.c \
src/ex_cmdidxs.h \
src/ex_cmds.c \
src/ex_cmds.h \
@@ -189,8 +191,10 @@ SRC_ALL = \
src/proto/digraph.pro \
src/proto/edit.pro \
src/proto/eval.pro \
+ src/proto/evalbuffer.pro \
src/proto/evalfunc.pro \
src/proto/evalvars.pro \
+ src/proto/evalwindow.pro \
src/proto/ex_cmds.pro \
src/proto/ex_cmds2.pro \
src/proto/ex_docmd.pro \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index 9f86cef72d..bd2dba26cd 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -721,8 +721,10 @@ OBJ = \
$(OUTDIR)/digraph.o \
$(OUTDIR)/edit.o \
$(OUTDIR)/eval.o \
+ $(OUTDIR)/evalbuffer.o \
$(OUTDIR)/evalfunc.o \
$(OUTDIR)/evalvars.o \
+ $(OUTDIR)/evalwindow.o \
$(OUTDIR)/ex_cmds.o \
$(OUTDIR)/ex_cmds2.o \
$(OUTDIR)/ex_docmd.o \
diff --git a/src/Make_morph.mak b/src/Make_morph.mak
index 09e514c249..3f896da5b6 100644
--- a/src/Make_morph.mak
+++ b/src/Make_morph.mak
@@ -41,8 +41,10 @@ SRC = arabic.c \
digraph.c \
edit.c \
eval.c \
+ evalbuffer.c \
evalfunc.c \
evalvars.c \
+ evalwindow.c \
ex_cmds.c \
ex_cmds2.c \
ex_docmd.c \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 31970faf32..0401902f22 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -728,8 +728,10 @@ OBJ = \
$(OUTDIR)\digraph.obj \
$(OUTDIR)\edit.obj \
$(OUTDIR)\eval.obj \
+ $(OUTDIR)\evalbuffer.obj \
$(OUTDIR)\evalfunc.obj \
$(OUTDIR)\evalvars.obj \
+ $(OUTDIR)\evalwindow.obj \
$(OUTDIR)\ex_cmds.obj \
$(OUTDIR)\ex_cmds2.obj \
$(OUTDIR)\ex_docmd.obj \
@@ -1485,10 +1487,14 @@ $(OUTDIR)/edit.obj: $(OUTDIR) edit.c $(INCL)
$(OUTDIR)/eval.obj: $(OUTDIR) eval.c $(INCL)
+$(OUTDIR)/evalbuffer.obj: $(OUTDIR) evalbuffer.c $(INCL)
+
$(OUTDIR)/evalfunc.obj: $(OUTDIR) evalfunc.c $(INCL)
$(OUTDIR)/evalvars.obj: $(OUTDIR) evalvars.c $(INCL)
+$(OUTDIR)/evalwindow.obj: $(OUTDIR) evalwindow.c $(INCL)
+
$(OUTDIR)/ex_cmds.obj: $(OUTDIR) ex_cmds.c $(INCL)
$(OUTDIR)/ex_cmds2.obj: $(OUTDIR) ex_cmds2.c $(INCL)
@@ -1775,8 +1781,10 @@ proto.h: \
proto/digraph.pro \
proto/edit.pro \
proto/eval.pro \
+ proto/evalbuffer.pro \
proto/evalfunc.pro \
proto/evalvars.pro \
+ proto/evalwindow.pro \
proto/ex_cmds.pro \
proto/ex_cmds2.pro \
proto/ex_docmd.pro \
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index 5b4075de83..607f564352 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -309,8 +309,10 @@ ALL_LIBS = $(LIBS) $(GUI_LIB_DIR) $(GUI_LIB) \
SRC = arabic.c arglist.c autocmd.c beval.c blob.c blowfish.c buffer.c \
change.c charset.c cmdexpand.c cmdhist.c crypt.c crypt_zip.c \
- debugger.c dict.c diff.c digraph.c edit.c eval.c evalfunc.c \
- evalvars.c ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c \
+ debugger.c dict.c diff.c digraph.c edit.c eval.c evalbuffer.c \
+ evalfunc.c \
+ evalvars.c evalwindow.c ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c \
+ ex_getln.c \
if_cscope.c if_xcmdsrv.c fileio.c filepath.c, findfile.c fold.c \
getchar.c hardcopy.c hashtab.c highlight.c \
indent.c insexpand.c json.c list.c main.c map.c mark.c menu.c mbyte.c \
@@ -327,7 +329,8 @@ SRC = arabic.c arglist.c autocmd.c beval.c blob.c blowfish.c buffer.c \
OBJ = arabic.obj arglist.obj autocmd.obj beval.obj blob.obj blowfish.obj \
buffer.obj change.obj charset.obj cmdexpand.obj cmdhist.obj \
crypt.obj crypt_zip.obj debugger.obj dict.obj diff.obj digraph.obj \
- edit.obj eval.obj evalfunc.obj evalvars.obj ex_cmds.obj ex_cmds2.obj \
+ edit.obj eval.obj evalbuffer.obj evalfunc.obj evalvars.obj \
+ evalwindow.obj ex_cmds.obj ex_cmds2.obj \
ex_docmd.obj ex_eval.obj ex_getln.obj if_cscope.obj if_xcmdsrv.obj \
fileio.obj filepath.obj \
findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \
@@ -567,6 +570,10 @@ eval.obj : eval.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \
version.h
+evalbuffer.obj : evalbuffer.c vim.h [.auto]config.h feature.h os_unix.h \
+ ascii.h keymap.h term.h macros.h option.h structs.h \
+ regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
+ proto.h globals.h version.h
evalfunc.obj : evalfunc.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
@@ -575,6 +582,10 @@ evalvars.obj : evalvars.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
proto.h globals.h version.h
+evalwindow.obj : evalwindow.c vim.h [.auto]config.h feature.h os_unix.h \
+ ascii.h keymap.h term.h macros.h option.h structs.h \
+ regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
+ proto.h globals.h version.h
ex_cmds.obj : ex_cmds.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
diff --git a/src/Makefile b/src/Makefile
index 840e3fe1e2..34d1c145af 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1595,8 +1595,10 @@ BASIC_SRC = \
digraph.c \
edit.c \
eval.c \
+ evalbuffer.c \
evalfunc.c \
evalvars.c \
+ evalwindow.c \
ex_cmds.c \
ex_cmds2.c \
ex_docmd.c \
@@ -1726,8 +1728,10 @@ OBJ_COMMON = \
objects/digraph.o \
objects/edit.o \
objects/eval.o \
+ objects/evalbuffer.o \
objects/evalfunc.o \
objects/evalvars.o \
+ objects/evalwindow.o \
objects/ex_cmds.o \
objects/ex_cmds2.o \
objects/ex_docmd.o \
@@ -1870,8 +1874,10 @@ PRO_AUTO = \
digraph.pro \
edit.pro \
eval.pro \
+ evalbuffer.pro \
evalfunc.pro \
evalvars.pro \
+ evalwindow.pro \
ex_cmds.pro \
ex_cmds2.pro \
ex_docmd.pro \
@@ -3080,12 +3086,18 @@ objects/edit.o: edit.c
objects/eval.o: eval.c
$(CCC) -o $@ eval.c
+objects/evalbuffer.o: evalbuffer.c
+ $(CCC) -o $@ evalbuffer.c
+
objects/evalfunc.o: evalfunc.c
$(CCC) -o $@ evalfunc.c
objects/evalvars.o: evalvars.c
$(CCC) -o $@ evalvars.c
+objects/evalwindow.o: evalwindow.c
+ $(CCC) -o $@ evalwindow.c
+
objects/ex_cmds.o: ex_cmds.c
$(CCC) -o $@ ex_cmds.c
@@ -3603,6 +3615,10 @@ objects/eval.o: eval.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h version.h
+objects/evalbuffer.o: evalbuffer.c vim.h protodef.h auto/config.h feature.h os_unix.h \
+ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
+ proto.h globals.h version.h
objects/evalfunc.o: evalfunc.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
@@ -3611,6 +3627,10 @@ objects/evalvars.o: evalvars.c vim.h protodef.h auto/config.h feature.h \
os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h
+objects/evalwindow.o: evalwindow.c vim.h protodef.h auto/config.h feature.h \
+ os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
+ proto.h globals.h
objects/ex_cmds.o: ex_cmds.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
diff --git a/src/README.md b/src/README.md
index dcc7a5c83c..6ba83910ee 100644
--- a/src/README.md
+++ b/src/README.md
@@ -33,8 +33,10 @@ cmdhist.c | command-line history
debugger.c | vim script debugger
diff.c | diff mode (vimdiff)
eval.c | expression evaluation
+evalbuffer.c | buffer related built-in functions
evalfunc.c | built-in functions
evalvars.c | vim variables
+evalwindow.c | window related built-in functions
fileio.c | reading and writing files
filepath.c | dealing with file names and paths
findfile.c | search for files in 'path'
diff --git a/src/buffer.c b/src/buffer.c
index c42dece642..81f2799f49 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5450,66 +5450,6 @@ buf_spname(buf_T *buf)
return NULL;
}
-#if defined(FEAT_JOB_CHANNEL) \
- || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
- || defined(PROTO)
-/*
- * Find a window for buffer "buf".
- * If found OK is returned and "wp" and "tp" are set to the window and tabpage.
- * If not found FAIL is returned.
- */
- static int
-find_win_for_buf(
- buf_T *buf,
- win_T **wp,
- tabpage_T **tp)
-{
- FOR_ALL_TAB_WINDOWS(*tp, *wp)
- if ((*wp)->w_buffer == buf)
- goto win_found;
- return FAIL;
-win_found:
- return OK;
-}
-
-/*
- * Find a window that contains "buf" and switch to it.
- * If there is no such window, use the current window and change "curbuf".
- * Caller must initialize save_curbuf to NULL.
- * restore_win_for_buf() MUST be called later!
- */
- void
-switch_to_win_for_buf(
- buf_T *buf,
- win_T **save_curwinp,
- tabpage_T **save_curtabp,
- bufref_T *save_curbuf)
-{
- win_T *wp;
- tabpage_T *tp;
-
- if (find_win_for_buf(buf, &wp, &tp) == FAIL)
- switch_buffer(save_curbuf, buf);
- else if (switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL)
- {
- restore_win(*save_curwinp, *save_curtabp, TRUE);
- switch_buffer(save_curbuf, buf);
- }
-}
-
- void
-restore_win_for_buf(
- win_T *save_curwin,
- tabpage_T *save_curtab,
- bufref_T *save_curbuf)
-{
- if (save_curbuf->br_buf == NULL)
- restore_win(save_curwin, save_curtab, TRUE);
- else
- restore_buffer(save_curbuf);
-}
-#endif
-
/*
* Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed.
*/
@@ -5603,48 +5543,3 @@ wipe_buffer(
if (!aucmd)
unblock_autocmds();
}
-
-#if defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Mark references in functions of buffers.
- */
- int
-set_ref_in_buffers(int copyID)
-{
- int abort = FALSE;
- buf_T *bp;
-
- FOR_ALL_BUFFERS(bp)
- {
- listener_T *lnr;
- typval_T tv;
-
- for (lnr = bp->b_listener; !abort && lnr != NULL; lnr = lnr->lr_next)
- {
- if (lnr->lr_callback.cb_partial != NULL)
- {
- tv.v_type = VAR_PARTIAL;
- tv.vval.v_partial = lnr->lr_callback.cb_partial;
- abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
- }
- }
-# ifdef FEAT_JOB_CHANNEL
- if (!abort && bp->b_prompt_callback.cb_partial != NULL)
- {
- tv.v_type = VAR_PARTIAL;
- tv.vval.v_partial = bp->b_prompt_callback.cb_partial;
- abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
- }
- if (!abort && bp->b_prompt_interrupt.cb_partial != NULL)
- {
- tv.v_type = VAR_PARTIAL;
- tv.vval.v_partial = bp->b_prompt_interrupt.cb_partial;
- abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
- }
-# endif
- if (abort)
- break;
- }
- return abort;
-}
-#endif
diff --git a/src/channel.c b/src/channel.c
index b4493cf752..e4dbcf6039 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1036,7 +1036,7 @@ prepare_buffer(buf_T *buf)
* Returns NULL if there is something very wrong (error already reported).
*/
static buf_T *
-find_buffer(char_u *name, int err, int msg)
+channel_find_buffer(char_u *name, int err, int msg)
{
buf_T *buf = NULL;
buf_T *save_curbuf = curbuf;
@@ -1126,7 +1126,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
if (opt->jo_set2 & JO2_OUT_MSG)
msg = opt->jo_message[PART_OUT];
- buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE, msg);
+ buf = channel_find_buffer(opt->jo_io_name[PART_OUT], FALSE, msg);
}
if (buf != NULL)
{
@@ -1173,7 +1173,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
if (opt->jo_set2 & JO2_ERR_MSG)
msg = opt->jo_message[PART_ERR];
- buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE, msg);
+ buf = channel_find_buffer(opt->jo_io_name[PART_ERR], TRUE, msg);
}
if (buf != NULL)
{
diff --git a/src/evalbuffer.c b/src/evalbuffer.c
new file mode 100644
index 0000000000..35c9ed2459
--- /dev/null
+++ b/src/evalbuffer.c
@@ -0,0 +1,887 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * evalbuffer.c: Buffer related builtin functions
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Mark references in functions of buffers.
+ */
+ int
+set_ref_in_buffers(int copyID)
+{
+ int abort = FALSE;
+ buf_T *bp;
+
+ FOR_ALL_BUFFERS(bp)
+ {
+ listener_T *lnr;
+ typval_T tv;
+
+ for (lnr = bp->b_listener; !abort && lnr != NULL; lnr = lnr->lr_next)
+ {
+ if (lnr->lr_callback.cb_partial != NULL)
+ {
+ tv.v_type = VAR_PARTIAL;
+ tv.vval.v_partial = lnr->lr_callback.cb_partial;
+ abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
+ }
+ }
+# ifdef FEAT_JOB_CHANNEL
+ if (!abort && bp->b_prompt_callback.cb_partial != NULL)
+ {
+ tv.v_type = VAR_PARTIAL;
+ tv.vval.v_partial = bp->b_prompt_callback.cb_partial;
+ abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
+ }
+ if (!abort && bp->b_prompt_interrupt.cb_partial != NULL)
+ {
+ tv.v_type = VAR_PARTIAL;
+ tv.vval.v_partial = bp->b_prompt_interrupt.cb_partial;
+ abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
+ }
+# endif
+ if (abort)
+ break;
+ }
+ return abort;
+}
+
+ buf_T *
+buflist_find_by_name(char_u *name, int curtab_only)
+{
+ int save_magic;
+ char_u *save_cpo;
+ buf_T *buf;
+
+ // Ignore 'magic' and 'cpoptions' here to make scripts portable
+ save_magic = p_magic;
+ p_magic = TRUE;
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
+ TRUE, FALSE, curtab_only));
+
+ p_magic = save_magic;
+ p_cpo = save_cpo;
+ return buf;
+}
+
+/*
+ * Find a buffer by number or exact name.
+ */
+ buf_T *
+find_buffer(typval_T *avar)
+{
+ buf_T *buf = NULL;
+
+ if (avar->v_type == VAR_NUMBER)
+ buf = buflist_findnr((int)avar->vval.v_number);
+ else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
+ {
+ buf = buflist_findname_exp(avar->vval.v_string);
+ if (buf == NULL)
+ {
+ // No full path name match, try a match with a URL or a "nofile"
+ // buffer, these don't use the full path.
+ FOR_ALL_BUFFERS(buf)
+ if (buf->b_fname != NULL
+ && (path_with_url(buf->b_fname)
+#ifdef FEAT_QUICKFIX
+ || bt_nofilename(buf)
+#endif
+ )
+ && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
+ break;
+ }
+ }
+ return buf;
+}
+
+/*
+ * If there is a window for "curbuf", make it the current window.
+ */
+ static void
+find_win_for_curbuf(void)
+{
+ wininfo_T *wip;
+
+ for (wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next)
+ {
+ if (wip->wi_win != NULL)
+ {
+ curwin = wip->wi_win;
+ break;
+ }
+ }
+}
+
+/*
+ * Set line or list of lines in buffer "buf".
+ */
+ static void
+set_buffer_lines(
+ buf_T *buf,
+ linenr_T lnum_arg,
+ int append,
+ typval_T *lines,
+ typval_T *rettv)
+{
+ linenr_T lnum = lnum_arg + (append ? 1 : 0);
+ char_u *line = NULL;
+ list_T *l = NULL;
+ listitem_T *li = NULL;
+ long added = 0;
+ linenr_T append_lnum;
+ buf_T *curbuf_save = NULL;
+ win_T *curwin_save = NULL;
+ int is_curbuf = buf == curbuf;
+
+ // When using the current buffer ml_mfp will be set if needed. Useful when
+ // setline() is used on startup. For other buffers the buffer must be
+ // loaded.
+ if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1)
+ {
+ rettv->vval.v_number = 1; // FAIL
+ return;
+ }
+
+ if (!is_curbuf)
+ {
+ curbuf_save = curbuf;
+ curwin_save = curwin;
+ curbuf = buf;
+ find_win_for_curbuf();
+ }
+
+ if (append)
+ // appendbufline() uses the line number below which we insert
+ append_lnum = lnum - 1;
+ else
+ // setbufline() uses the line number above which we insert, we only
+ // append if it's below the last line
+ append_lnum = curbuf->b_ml.ml_line_count;
+
+ if (lines->v_type == VAR_LIST)
+ {
+ l = lines->vval.v_list;
+ li = l->lv_first;
+ }
+ else
+ line = tv_get_string_chk(lines);
+
+ // default result is zero == OK
+ for (;;)
+ {
+ if (l != NULL)
+ {
+ // list argument, get next string
+ if (li == NULL)
+ break;
+ line = tv_get_string_chk(&li->li_tv);
+ li = li->li_next;
+ }
+
+ rettv->vval.v_number = 1; // FAIL
+ if (line == NULL || 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 (!append && lnum <= curbuf->b_ml.ml_line_count)
+ {
+ // Existing line, replace it.
+ // Removes any existing text properties.
+ if (u_savesub(lnum) == OK && ml_replace_len(
+ lnum, line, (colnr_T)STRLEN(line) + 1, TRUE, 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)
+ {
+ // 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)
+ {
+ win_T *wp;
+ tabpage_T *tp;
+
+ appended_lines_mark(append_lnum, added);
+
+ // Only adjust the cursor for buffers other than the current, unless it
+ // is the current window. For curbuf and other windows it has been
+ // done in mark_adjust_internal().
+ FOR_ALL_TAB_WINDOWS(tp, wp)
+ if (wp->w_buffer == buf
+ && (wp->w_buffer != curbuf || wp == curwin)
+ && wp->w_cursor.lnum > append_lnum)
+ wp->w_cursor.lnum += added;
+ check_cursor_col();
+ update_topline();
+ }
+
+ if (!is_curbuf)
+ {
+ curbuf = curbuf_save;
+ curwin = curwin_save;
+ }
+}
+
+/*
+ * "append(lnum, string/list)" function
+ */
+ void
+f_append(typval_T *argvars, typval_T *rettv)
+{
+ linenr_T lnum = tv_get_lnum(&argvars[0]);
+
+ set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv);
+}
+
+/*
+ * "appendbufline(buf, lnum, string/list)" function
+ */
+ void
+f_appendbufline(typval_T *argvars, typval_T *rettv)
+{
+ linenr_T lnum;
+ buf_T *buf;
+
+ buf = tv_get_buf(&argvars[0], FALSE);
+ if (buf == NULL)
+ rettv->vval.v_number = 1; // FAIL
+ else
+ {
+ lnum = tv_get_lnum_buf(&argvars[1], buf);
+ set_buffer_lines(buf, lnum, TRUE, &argvars[2], rettv);
+ }
+}
+
+/*
+ * "bufadd(expr)" function
+ */
+ void
+f_bufadd(typval_T *argvars, typval_T *rettv)
+{
+ char_u *name = tv_get_string(&argvars[0]);
+
+ rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0);
+}
+
+/*
+ * "bufexists(expr)" function
+ */
+ void
+f_bufexists(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
+}
+
+/*
+ * "buflisted(expr)" function
+ */
+ void
+f_buflisted(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf;
+
+ buf = find_buffer(&argvars[0]);
+ rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
+}
+
+/*
+ * "bufload(expr)" function
+ */
+ void
+f_bufload(typval_T *argvars, typval_T *rettv UNUSED)
+{
+ buf_T *buf = get_buf_arg(&argvars[0]);
+
+ if (buf != NULL)
+ buffer_ensure_loaded(buf);
+}
+
+/*
+ * "bufloaded(expr)" function
+ */
+ void
+f_bufloaded(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf;
+
+ buf = find_buffer(&argvars[0]);
+ rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
+}
+
+/*
+ * "bufname(expr)" function
+ */
+ void
+f_bufname(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf;
+
+ if (argvars[0].v_type == VAR_UNKNOWN)
+ buf = curbuf;
+ else
+ {
+ (void)tv_get_number(&argvars[0]); // issue errmsg if type error
+ ++emsg_off;
+ buf = tv_get_buf(&argvars[0], FALSE);
+ --emsg_off;
+ }
+ rettv->v_type = VAR_STRING;
+ if (buf != NULL && buf->b_fname != NULL)
+ rettv->vval.v_string = vim_strsave(buf->b_fname);
+ else
+ rettv->vval.v_string = NULL;
+}
+
+/*
+ * "bufnr(expr)" function
+ */
+ void
+f_bufnr(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf;
+ int error = FALSE;
+ char_u *name;
+
+ if (argvars[0].v_type == VAR_UNKNOWN)
+ buf = curbuf;
+ else
+ {
+ (void)tv_get_number(&argvars[0]); // issue errmsg if type error
+ ++emsg_off;
+ buf = tv_get_buf(&argvars[0], FALSE);
+ --emsg_off;
+ }
+
+ // If the buffer isn't found and the second argument is not zero create a
+ // new buffer.
+ if (buf == NULL
+ && argvars[1].v_type != VAR_UNKNOWN
+ && tv_get_number_chk(&argvars[1], &error) != 0
+ && !error
+ && (name = tv_get_string_chk(&argvars[0])) != NULL
+ && !error)
+ buf = buflist_new(name, NULL, (linenr_T)1, 0);
+
+ if (buf != NULL)
+ rettv->vval.v_number = buf->b_fnum;
+ else
+ rettv->vval.v_number = -1;
+}
+
+ static void
+buf_win_common(typval_T *argvars, typval_T *rettv, int get_nr)
+{
+ win_T *wp;
+ int winnr = 0;
+ buf_T *buf;
+
+ (void)tv_get_number(&argvars[0]); // issue errmsg if type error
+ ++emsg_off;
+ buf = tv_get_buf(&argvars[0], TRUE);
+ FOR_ALL_WINDOWS(wp)
+ {
+ ++winnr;
+ if (wp->w_buffer == buf)
+ break;
+ }
+ rettv->vval.v_number = (wp != NULL ? (get_nr ? winnr : wp->w_id) : -1);
+ --emsg_off;
+}
+
+/*
+ * "bufwinid(nr)" function
+ */
+ void
+f_bufwinid(typval_T *argvars, typval_T *rettv)
+{
+ buf_win_common(argvars, rettv, FALSE);
+}
+
+/*
+ * "bufwinnr(nr)" function
+ */
+ void
+f_bufwinnr(typval_T *argvars, typval_T *rettv)
+{
+ buf_win_common(argvars, rettv, TRUE);
+}
+
+/*
+ * "deletebufline()" function
+ */
+ void
+f_deletebufline(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf;
+ linenr_T first, last;
+ linenr_T lnum;
+ long count;
+ int is_curbuf;
+ buf_T *curbuf_save = NULL;
+ win_T *curwin_save = NULL;
+ tabpage_T *tp;
+ win_T *wp;
+
+ buf = tv_get_buf(&argvars[0], FALSE);
+ if (buf == NULL)
+ {
+ rettv->vval.v_number = 1; // FAIL
+ return;
+ }
+ is_curbuf = buf == curbuf;
+
+ first = tv_get_lnum_buf(&argvars[1], buf);
+ if (argvars[2].v_type != VAR_UNKNOWN)
+ last = tv_get_lnum_buf(&argvars[2], buf);
+ else
+ last = first;
+
+ if (buf->b_ml.ml_mfp == NULL || first < 1
+ || first > buf->b_ml.ml_line_count || last < first)
+ {
+ rettv->vval.v_number = 1; // FAIL
+ return;
+ }
+
+ if (!is_curbuf)
+ {
+ curbuf_save = curbuf;
+ curwin_save = curwin;
+ curbuf = buf;
+ find_win_for_curbuf();
+ }
+ if (last > curbuf->b_ml.ml_line_count)
+ last = curbuf->b_ml.ml_line_count;
+ count = last - first + 1;
+
+ // 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 (u_save(first - 1, last + 1) == FAIL)
+ {
+ rettv->vval.v_number = 1; // FAIL
+ return;
+ }
+
+ for (lnum = first; lnum <= last; ++lnum)
+ ml_delete(first, TRUE);
+
+ FOR_ALL_TAB_WINDOWS(tp, wp)
+ if (wp->w_buffer == buf)
+ {
+ if (wp->w_cursor.lnum > last)
+ wp->w_cursor.lnum -= count;
+ else if (wp->w_cursor.lnum> first)
+ wp->w_cursor.lnum = first;
+ if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
+ wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count;
+ }
+ check_cursor_col();
+ deleted_lines_mark(first, count);
+
+ if (!is_curbuf)
+ {
+ curbuf = curbuf_save;
+ curwin = curwin_save;
+ }
+}
+
+/*
+ * Returns buffer options, variables and other attributes in a dictionary.
+ */
+ static dict_T *
+get_buffer_info(buf_T *buf)
+{
+ dict_T *dict;
+ tabpage_T *tp;
+ win_T *wp;
+ list_T *windows;
+
+ dict = dict_alloc();
+ if (dict == NULL)
+ return NULL;
+
+ dict_add_number(dict, "bufnr", buf->b_fnum);
+ dict_add_string(dict, "name", buf->b_ffname);
+ dict_add_number(dict, "lnum", buf == curbuf ? curwin->w_cursor.lnum
+ : buflist_findlnum(buf));
+ dict_add_number(dict, "loaded", buf->b_ml.ml_mfp != NULL);
+ dict_add_number(dict, "listed", buf->b_p_bl);
+ dict_add_number(dict, "changed", bufIsChanged(buf));
+ dict_add_number(dict, "changedtick", CHANGEDTICK(buf));
+ dict_add_number(dict, "hidden",
+ buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0);
+
+ // Get a reference to buffer variables
+ dict_add_dict(dict, "variables", buf->b_vars);
+
+ // List of windows displaying this buffer
+ windows = list_alloc();
+ if (windows != NULL)
+ {
+ FOR_ALL_TAB_WINDOWS(tp, wp)
+ if (wp->w_buffer == buf)
+ list_append_number(windows, (varnumber_T)wp->w_id);
+ dict_add_list(dict, "windows", windows);
+ }
+
+#ifdef FEAT_TEXT_PROP
+ // List of popup windows displaying this buffer
+ windows = list_alloc();
+ if (windows != NULL)
+ {
+ for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ list_append_number(windows, (varnumber_T)wp->w_id);
+ FOR_ALL_TABPAGES(tp)
+ for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ list_append_number(windows, (varnumber_T)wp->w_id);
+
+ dict_add_list(dict, "popups", windows);
+ }
+#endif
+
+#ifdef FEAT_SIGNS
+ if (buf->b_signlist != NULL)
+ {
+ // List of signs placed in this buffer
+ list_T *signs = list_alloc();
+ if (signs != NULL)
+ {
+ get_buffer_signs(buf, signs);
+ dict_add_list(dict, "signs", signs);
+ }
+ }
+#endif
+
+ return dict;
+}
+
+/*
+ * "getbufinfo()" function
+ */
+ void
+f_getbufinfo(typval_T *argvars, typval_T *rettv)
+{
+ buf_T *buf = NULL;
+ buf_T *argbuf = NULL;
+ dict_T *d;
+ int filtered = FALSE;
+ int sel_buflisted = FALSE;
+ int sel_bufloaded = FALSE;
+ int sel_bufmodified = FALSE;
+
+ if (rettv_list_alloc(rettv) != OK)
+ return;
+
+ // List of all the buffers or selected buffers
+ if (argvars[0].v_type == VAR_DICT)
+ {
+ dict_T *sel_d = argvars[0].vval.v_dict;
+
+ if (sel_d != NULL)
<