diff options
| author | ZyX <kp-pav@yandex.ru> | 2015-04-25 18:47:31 +0300 |
|---|---|---|
| committer | ZyX <kp-pav@yandex.ru> | 2015-10-08 21:59:51 +0300 |
| commit | 244dbe3a77bf548f73d8781da7327f30e818b08a (patch) | |
| tree | 8777a25447be219fe351106cfef37670e0278ddd /src/nvim | |
| parent | 0fdaab995ed95250b13058a717d5bc562e1834c8 (diff) | |
| download | rneovim-244dbe3a77bf548f73d8781da7327f30e818b08a.tar.gz rneovim-244dbe3a77bf548f73d8781da7327f30e818b08a.tar.bz2 rneovim-244dbe3a77bf548f73d8781da7327f30e818b08a.zip | |
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
Diffstat (limited to 'src/nvim')
34 files changed, 4361 insertions, 1816 deletions
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index f29deb53f9..a0f14ac7a4 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -69,6 +69,8 @@ #define ADD(array, item) \ kv_push(Object, array, item) +#define STATIC_CSTR_AS_STRING(s) ((String) {.data = s, .size = sizeof(s) - 1}) + // Helpers used by the generated msgpack-rpc api wrappers #define api_init_boolean #define api_init_integer diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index af801c6f1a..3d8a75febd 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -84,7 +84,7 @@ return { 'User', -- user defined autocommand 'VimEnter', -- after starting Vim 'VimLeave', -- before exiting Vim - 'VimLeavePre', -- before exiting Vim and writing .viminfo + 'VimLeavePre', -- before exiting Vim and writing ShaDa file 'VimResized', -- after Vim window was resized 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b212e75283..5ebeec1b70 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -73,6 +73,7 @@ #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/window.h" +#include "nvim/shada.h" #include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/os/input.h" @@ -555,6 +556,12 @@ static void free_buffer(buf_T *buf) free_buffer_stuff(buf, TRUE); unref_var_dict(buf->b_vars); aubuflocal_remove(buf); + free_fmark(buf->b_last_cursor); + free_fmark(buf->b_last_insert); + free_fmark(buf->b_last_change); + for (size_t i = 0; i < NMARKS; i++) { + free_fmark(buf->b_namedm[i]); + } if (autocmd_busy) { // Do not free the buffer structure while autocommands are executing, // it's still needed. Free it when autocmd_busy is reset. @@ -4164,93 +4171,6 @@ chk_modeline ( return retval; } -int read_viminfo_bufferlist(vir_T *virp, int writing) -{ - char_u *tab; - linenr_T lnum; - colnr_T col; - buf_T *buf; - char_u *sfname; - char_u *xline; - - /* Handle long line and escaped characters. */ - xline = viminfo_readstring(virp, 1, FALSE); - - /* don't read in if there are files on the command-line or if writing: */ - if (xline != NULL && !writing && ARGCOUNT == 0 - && find_viminfo_parameter('%') != NULL) { - /* Format is: <fname> Tab <lnum> Tab <col>. - * Watch out for a Tab in the file name, work from the end. */ - lnum = 0; - col = 0; - tab = vim_strrchr(xline, '\t'); - if (tab != NULL) { - *tab++ = '\0'; - col = (colnr_T)atoi((char *)tab); - tab = vim_strrchr(xline, '\t'); - if (tab != NULL) { - *tab++ = '\0'; - lnum = atol((char *)tab); - } - } - - /* Expand "~/" in the file name at "line + 1" to a full path. - * Then try shortening it by comparing with the current directory */ - expand_env(xline, NameBuff, MAXPATHL); - sfname = path_shorten_fname_if_possible(NameBuff); - - buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED); - if (buf != NULL) { /* just in case... */ - buf->b_last_cursor.lnum = lnum; - buf->b_last_cursor.col = col; - buflist_setfpos(buf, curwin, lnum, col, FALSE); - } - } - xfree(xline); - - return viminfo_readline(virp); -} - -void write_viminfo_bufferlist(FILE *fp) -{ - char_u *line; - int max_buffers; - - if (find_viminfo_parameter('%') == NULL) - return; - - /* Without a number -1 is returned: do all buffers. */ - max_buffers = get_viminfo_parameter('%'); - - /* Allocate room for the file name, lnum and col. */ -#define LINE_BUF_LEN (MAXPATHL + 40) - line = xmalloc(LINE_BUF_LEN); - - FOR_ALL_TAB_WINDOWS(tp, win) { - set_last_cursor(win); - } - - fputs(_("\n# Buffer list:\n"), fp); - FOR_ALL_BUFFERS(buf) { - if (buf->b_fname == NULL - || !buf->b_p_bl - || bt_quickfix(buf) - || removable(buf->b_ffname)) - continue; - - if (max_buffers-- == 0) - break; - putc('%', fp); - home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE); - vim_snprintf_add((char *)line, LINE_BUF_LEN, "\t%" PRId64 "\t%d", - (int64_t)buf->b_last_cursor.lnum, - buf->b_last_cursor.col); - viminfo_writestring(fp, line); - } - xfree(line); -} - - /* * Return special buffer name. * Returns NULL when the buffer has a normal file name. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 98fbef9c87..6fbdea2c62 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -327,15 +327,6 @@ typedef struct { bool vc_fail; /* fail for invalid char, don't use '?' */ } vimconv_T; -/* - * Structure used for reading from the viminfo file. - */ -typedef struct { - char_u *vir_line; /* text of the current line */ - FILE *vir_fd; /* file descriptor */ - vimconv_T vir_conv; /* encoding conversion */ -} vir_T; - #define CONV_NONE 0 #define CONV_TO_UTF8 1 #define CONV_9_TO_UTF8 2 @@ -515,16 +506,16 @@ struct file_buffer { uint64_t b_orig_size; /* size of original file in bytes */ int b_orig_mode; /* mode of original file */ - pos_T b_namedm[NMARKS]; /* current named marks (mark.c) */ + fmark_T b_namedm[NMARKS]; /* current named marks (mark.c) */ /* These variables are set when VIsual_active becomes FALSE */ visualinfo_T b_visual; int b_visual_mode_eval; /* b_visual.vi_mode for visualmode() */ - pos_T b_last_cursor; /* cursor position when last unloading this + fmark_T b_last_cursor; /* cursor position when last unloading this buffer */ - pos_T b_last_insert; /* where Insert mode was left */ - pos_T b_last_change; /* position of last change: '. mark */ + fmark_T b_last_insert; /* where Insert mode was left */ + fmark_T b_last_change; /* position of last change: '. mark */ /* * the changelist contains old change positions @@ -553,7 +544,7 @@ struct file_buffer { pos_T b_op_start_orig; // used for Insstart_orig pos_T b_op_end; - bool b_marks_read; /* Have we read viminfo marks yet? */ + bool b_marks_read; /* Have we read ShaDa marks yet? */ /* * The following only used in undo.c. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 427623e052..310191ba06 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -60,6 +60,7 @@ #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/event/loop.h" +#include "nvim/mark.h" #include "nvim/os/input.h" #include "nvim/os/time.h" @@ -6991,8 +6992,9 @@ ins_esc ( curwin->w_set_curswant = TRUE; /* Remember the last Insert position in the '^ mark. */ - if (!cmdmod.keepjumps) - curbuf->b_last_insert = curwin->w_cursor; + if (!cmdmod.keepjumps) { + RESET_FMARK(&curbuf->b_last_insert, curwin->w_cursor, curbuf->b_fnum); + } /* * The cursor should end up on the last inserted character. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 65afd19bbe..5a7d4702d2 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -354,7 +354,7 @@ typedef struct { typedef enum { VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */ VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */ - VAR_FLAVOUR_VIMINFO /* all uppercase */ + VAR_FLAVOUR_SHADA /* all uppercase */ } var_flavour_T; /* values for vv_flags: */ @@ -10482,6 +10482,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "scrollbind", "showcmd", "cmdline_info", + "shada", "signs", "smartindent", "startuptime", @@ -10498,7 +10499,6 @@ static void f_has(typval_T *argvars, typval_T *rettv) "title", "user-commands", /* was accidentally included in 5.4 */ "user_commands", - "viminfo", "vertsplit", "virtualedit", "visual", @@ -20712,107 +20712,62 @@ static var_flavour_T var_flavour(char_u *varname) while (*(++p)) if (ASCII_ISLOWER(*p)) return VAR_FLAVOUR_SESSION; - return VAR_FLAVOUR_VIMINFO; + return VAR_FLAVOUR_SHADA; } else return VAR_FLAVOUR_DEFAULT; } -/* - * Restore global vars that start with a capital from the viminfo file - */ -int read_viminfo_varlist(vir_T *virp, int writing) -{ - char_u *tab; - int type = VAR_NUMBER; - typval_T tv; - - if (!writing && (find_viminfo_parameter('!') != NULL)) { - tab = vim_strchr(virp->vir_line + 1, '\t'); - if (tab != NULL) { - *tab++ = NUL; /* isolate the variable name */ - switch (*tab) { - case 'S': type = VAR_STRING; break; - case 'F': type = VAR_FLOAT; break; - case 'D': type = VAR_DICT; break; - case 'L': type = VAR_LIST; break; - } - - tab = vim_strchr(tab, '\t'); - if (tab != NULL) { - tv.v_type = type; - if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST) - tv.vval.v_string = viminfo_readstring(virp, - (int)(tab - virp->vir_line + 1), TRUE); - else if (type == VAR_FLOAT) - (void)string2float(tab + 1, &tv.vval.v_float); - else - tv.vval.v_number = atol((char *)tab + 1); - if (type == VAR_DICT || type == VAR_LIST) { - typval_T *etv = eval_expr(tv.vval.v_string, NULL); - - if (etv == NULL) - /* Failed to parse back the dict or list, use it as a - * string. */ - tv.v_type = VAR_STRING; - else { - xfree(tv.vval.v_string); - tv = *etv; - xfree(etv); - } - } - - set_var(virp->vir_line + 1, &tv, FALSE); - - if (tv.v_type == VAR_STRING) - xfree(tv.vval.v_string); - else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST) - clear_tv(&tv); - } +/// Iterate over global variables +/// +/// @warning No modifications to global variable dictionary must be performed +/// while iteration is in progress. +/// +/// @param[in] iter Iterator. Pass NULL to start iteration. +/// @param[out] name Variable name. +/// @param[out] rettv Variable value. +/// +/// @return Pointer that needs to be passed to next `var_shada_iter` invocation +/// or NULL to indicate that iteration is over. +const void *var_shada_iter(const void *const iter, const char **const name, + typval_T *rettv) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3) +{ + const hashitem_T *hi; + const hashitem_T *hifirst = globvarht.ht_array; + const size_t hinum = (size_t) globvarht.ht_mask + 1; + *name = NULL; + if (iter == NULL) { + hi = globvarht.ht_array; + while ((HASHITEM_EMPTY(hi) + || var_flavour(HI2DI(hi)->di_key) != VAR_FLAVOUR_SHADA) + && (size_t) (hi - hifirst) < hinum) { + hi++; + } + if (HASHITEM_EMPTY(hi) + || var_flavour(HI2DI(hi)->di_key) != VAR_FLAVOUR_SHADA) { + *rettv = (typval_T) {.v_type = VAR_UNKNOWN}; + return NULL; } + } else { + hi = (const hashitem_T *) iter; } - - return viminfo_readline(virp); + *name = (char *) HI2DI(hi)->di_key; + copy_tv(&(HI2DI(hi)->di_tv), rettv); + while ((size_t) (++hi - hifirst) < hinum) { + if (!HASHITEM_EMPTY(hi) + && var_flavour(HI2DI(hi)->di_key) == VAR_FLAVOUR_SHADA) { + return hi; + } + } + return NULL; } -/* - * Write global vars that start with a capital to the viminfo file - */ -void write_viminfo_varlist(FILE *fp) +void var_set_global(const char *const name, typval_T vartv) { - hashitem_T *hi; - dictitem_T *this_var; - int todo; - char *s; - char_u *p; - - if (find_viminfo_parameter('!') == NULL) - return; - - fputs(_("\n# global variables:\n"), fp); - - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - this_var = HI2DI(hi); - if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO) { - switch (this_var->di_tv.v_type) { - case VAR_STRING: s = "STR"; break; - case VAR_NUMBER: s = "NUM"; break; - case VAR_FLOAT: s = "FLO"; break; - case VAR_DICT: s = "DIC"; break; - case VAR_LIST: s = "LIS"; break; - default: continue; - } - fprintf(fp, "!%s\t%s\t", this_var->di_key, s); - p = (char_u *) echo_string(&this_var->di_tv, NULL); - if (p != NULL) { - viminfo_writestring(fp, p); - } - xfree(p); - } - } - } + funccall_T *const saved_current_funccal = current_funccal; + current_funccal = NULL; + set_var((char_u *) name, &vartv, false); + current_funccal = saved_current_funccal; } int store_session_globals(FILE *fd) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 81abf2fa63..262150a8c0 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -67,6 +67,9 @@ #include "nvim/os/os.h" #include "nvim/os/shell.h" #include "nvim/os/input.h" +#include "nvim/os/time.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" /* * Struct to hold the sign properties. @@ -1391,550 +1394,6 @@ void append_redir(char_u *buf, int buflen, char_u *opt, char_u *fname) (char *)opt, (char *)fname); } - -static int viminfo_errcnt; - -static int no_viminfo(void) -{ - /* "vim -i NONE" does not read or write a viminfo file */ - return use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0; -} - -/* - * Report an error for reading a viminfo file. - * Count the number of errors. When there are more than 10, return TRUE. - */ -int viminfo_error(char *errnum, char *message, char_u *line) -{ - vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "), - errnum, message); - STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1); - if (IObuff[STRLEN(IObuff) - 1] == '\n') - IObuff[STRLEN(IObuff) - 1] = NUL; - emsg(IObuff); - if (++viminfo_errcnt >= 10) { - EMSG(_("E136: viminfo: Too many errors, skipping rest of file")); - return TRUE; - } - return FALSE; -} - -/* - * read_viminfo() -- Read the viminfo file. Registers etc. which are already - * set are not over-written unless "flags" includes VIF_FORCEIT. -- webb - */ -int -read_viminfo ( - char_u *file, /* file name or NULL to use default name */ - int flags /* VIF_WANT_INFO et al. */ -) -{ - FILE *fp; - char_u *fname; - - if (no_viminfo()) - return FAIL; - - fname = viminfo_filename(file); /* get file name in allocated buffer */ - fp = mch_fopen((char *)fname, READBIN); - - if (p_verbose > 0) { - verbose_enter(); - smsg(_("Reading viminfo file \"%s\"%s%s%s"), - fname, - (flags & VIF_WANT_INFO) ? _(" info") : "", - (flags & VIF_WANT_MARKS) ? _(" marks") : "", - (flags & VIF_GET_OLDFILES) ? _(" oldfiles") : "", - fp == NULL ? _(" FAILED") : ""); - verbose_leave(); - } - - xfree(fname); - if (fp == NULL) - return FAIL; - - viminfo_errcnt = 0; - do_viminfo(fp, NULL, flags); - - fclose(fp); - return OK; -} - -/* - * Write the viminfo file. The old one is read in first so that effectively a - * merge of current info and old info is done. This allows multiple vims to - * run simultaneously, without losing any marks etc. - * If "forceit" is TRUE, then the old file is not read in, and only internal - * info is written to the file. - */ -void write_viminfo(char_u *file, int forceit) -{ - char_u *fname; - FILE *fp_in = NULL; /* input viminfo file, if any */ - FILE *fp_out = NULL; /* output viminfo file */ - char_u *tempname = NULL; /* name of temp viminfo file */ - char_u *wp; -#if defined(UNIX) - mode_t umask_save; -#endif - - if (no_viminfo()) - return; - - fname = viminfo_filename(file); /* may set to default if NULL */ - - fp_in = mch_fopen((char *)fname, READBIN); - if (fp_in == NULL) { - /* if it does exist, but we can't read it, don't try writing */ - if (os_file_exists(fname)) - goto end; -#if defined(UNIX) - /* - * For Unix we create the .viminfo non-accessible for others, - * because it may contain text from non-accessible documents. - */ - umask_save = umask(077); -#endif - fp_out = mch_fopen((char *)fname, WRITEBIN); -#if defined(UNIX) - (void)umask(umask_save); -#endif - } else { - /* - * There is an existing viminfo file. Create a temporary file to - * write the new viminfo into, in the same directory as the - * existing viminfo file, which will be renamed later. - */ -#ifdef UNIX - /* - * For Unix we check the owner of the file. It's not very nice to - * overwrite a user's viminfo file after a "su root", with a - * viminfo file that the user can't read. - */ - - FileInfo old_info; // FileInfo of existing viminfo file - if (os_fileinfo((char *)fname, &old_info) - && getuid() != ROOT_UID - && !(old_info.stat.st_uid == getuid() - ? (old_info.stat.st_mode & 0200) - : (old_info.stat.st_gid == getgid() - ? (old_info.stat.st_mode & 0020) - : (old_info.stat.st_mode & 0002)))) { - int tt = msg_didany; - - /* avoid a wait_return for this message, it's annoying */ - EMSG2(_("E137: Viminfo file is not writable: %s"), fname); - msg_didany = tt; - fclose(fp_in); - goto end; - } -#endif - - // Make tempname - tempname = (char_u *)modname((char *)fname, ".tmp", FALSE); - if (tempname != NULL) { - /* - * Check if tempfile already exists. Never overwrite an - * existing file! - */ - if (os_file_exists(tempname)) { - /* - * Try another name. Change one character, just before - * the extension. - */ - wp = tempname + STRLEN(tempname) - 5; - if (wp < path_tail(tempname)) /* empty file name? */ - wp = path_tail(tempname); - for (*wp = 'z'; os_file_exists(tempname); --*wp) { - /* - * They all exist? Must be something wrong! Don't - * write the viminfo file then. - */ - if (*wp == 'a') { - xfree(tempname); - tempname = NULL; - break; - } - } - } - } - - if (tempname != NULL) { - int fd; - - /* Use os_open() to be able to use O_NOFOLLOW and set file - * protection: - * Unix: same as original file, but strip s-bit. Reset umask to - * avoid it getting in the way. - * Others: r&w for user only. */ -# ifdef UNIX - umask_save = umask(0); - fd = os_open((char *)tempname, - O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, - (int)((old_info.stat.st_mode & 0777) | 0600)); - (void)umask(umask_save); -# else - fd = os_open((char *)tempname, - O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600); -# endif - if (fd < 0) - fp_out = NULL; - else - fp_out = fdopen(fd, WRITEBIN); - - /* - * If we can't create in the same directory, try creating a - * "normal" temp file. - */ - if (fp_out == NULL) { - xfree(tempname); - if ((tempname = vim_tempname()) != NULL) - fp_out = mch_fopen((char *)tempname, WRITEBIN); - } - -#ifdef UNIX - /* - * Make sure the owner can read/write it. This only works for - * root. - */ - if (fp_out != NULL) { - os_fchown(fileno(fp_out), old_info.stat.st_uid, old_info.stat.st_gid); - } -#endif - } - } - - /* - * Check if the new viminfo file can be written to. - */ - if (fp_out == NULL) { - EMSG2(_("E138: Can't write viminfo file %s!"), - (fp_in == NULL || tempname == NULL) ? fname : tempname); - if (fp_in != NULL) - fclose(fp_in); - goto end; - } - - if (p_verbose > 0) { - verbose_enter(); - smsg(_("Writing viminfo file \"%s\""), fname); - verbose_leave(); - } - - viminfo_errcnt = 0; - do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS)); - - fclose(fp_out); /* errors are ignored !? */ - if (fp_in != NULL) { - fclose(fp_in); - - /* In case of an error keep the original viminfo file. Otherwise - * rename the newly written file. Give an error if that fails. */ - if (viminfo_errcnt == 0 && vim_rename(tempname, fname) == -1) { - viminfo_errcnt++; - EMSG2(_("E886: Can't rename viminfo file to %s!"), fname); - } - if (viminfo_errcnt > 0) { - os_remove((char *)tempname); - } - } - -end: - xfree(fname); - xfree(tempname); -} - -/* - * Get the viminfo file name to use. - * If "file" is given and not empty, use it (has already been expanded by - * cmdline functions). - * Otherwise use "-i file_name", value from 'viminfo' or the default, and - * expand environment variables. - * Returns an allocated string. - */ -static char_u *viminfo_filename(char_u *file) -{ - if (file == NULL || *file == NUL) { - if (use_viminfo != NULL) - file = use_viminfo; - else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL) { -#ifdef VIMINFO_FILE2 - // don't use $HOME when not defined (turned into "c:/"!). - if (!os_env_exists("HOME")) { - // don't use $VIM when not available. - expand_env((char_u *)"$VIM", NameBuff, MAXPATHL); - if (STRCMP("$VIM", NameBuff) != 0) /* $VIM was expanded */ - file = (char_u *)VIMINFO_FILE2; - else - file = (char_u *)VIMINFO_FILE; - } else -#endif - file = (char_u *)VIMINFO_FILE; - } - expand_env(file, NameBuff, MAXPATHL); - file = NameBuff; - } - return vim_strsave(file); -} - -/* - * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo(). - */ -static void do_viminfo(FILE *fp_in, FILE *fp_out, int flags) -{ - int count = 0; - int eof = FALSE; - vir_T vir; - int merge = FALSE; - - vir.vir_line = xmalloc(LSIZE); - vir.vir_fd = fp_in; - vir.vir_conv.vc_type = CONV_NONE; - - if (fp_in != NULL) { - if (flags & VIF_WANT_INFO) { - eof = read_viminfo_up_to_marks(&vir, - flags & VIF_FORCEIT, fp_out != NULL); - merge = TRUE; - } else if (flags != 0) - /* Skip info, find start of marks */ - while (!(eof = viminfo_readline(&vir)) - && vir.vir_line[0] != '>') - ; - } - if (fp_out != NULL) { - /* Write the info: */ - fprintf(fp_out, _("# This viminfo file was generated by Nvim %s.\n"), - mediumVersion); - fputs(_("# You may edit it if you're careful!\n\n"), fp_out); - fputs(_("# Value of 'encoding' when this file was written\n"), fp_out); - fprintf(fp_out, "*encoding=%s\n\n", p_enc); - write_viminfo_search_pattern(fp_out); - write_viminfo_sub_string(fp_out); - write_viminfo_history(fp_out, merge); - write_viminfo_registers(fp_out); - write_viminfo_varlist(fp_out); - write_viminfo_filemarks(fp_out); - write_viminfo_bufferlist(fp_out); - count = write_viminfo_marks(fp_out); - } - if (fp_in != NULL - && (flags & (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT))) - copy_viminfo_marks(&vir, fp_out, count, eof, flags); - - xfree(vir.vir_line); - if (vir.vir_conv.vc_type != CONV_NONE) - convert_setup(&vir.vir_conv, NULL, NULL); -} - -/* - * read_viminfo_up_to_marks() -- Only called from do_viminfo(). Reads in the - * first part of the viminfo file which contains everything but the marks that - * are local to a file. Returns TRUE when end-of-file is reached. -- webb - */ -static int read_viminfo_up_to_marks(vir_T *virp, int forceit, int writing) -{ - int eof; - - prepare_viminfo_history(forceit ? 9999 : 0, writing); - eof = viminfo_readline(virp); - while (!eof && virp->vir_line[0] != '>') { - switch (virp->vir_line[0]) { - /* Characters reserved for future expansion, ignored now */ - case '+': /* "+40 /path/dir file", for running vim without args */ - case '|': /* to be defined */ - case '^': /* to be defined */ - case '<': /* long line - ignored */ - /* A comment or empty line. */ - case NUL: - case '\r': - case '\n': - case '#': - eof = viminfo_readline(virp); - break; - case '*': /* "*encoding=value" */ - eof = viminfo_encoding(virp); - break; - case '!': /* global variable */ - eof = read_viminfo_varlist(virp, writing); - break; - case '%': /* entry for buffer list */ - eof = read_viminfo_bufferlist(virp, writing); - break; - case '"': - eof = read_viminfo_register(virp, forceit); - break; - case '/': /* Search string */ - case '&': /* Substitute search string */ - case '~': /* Last search string, followed by '/' or '&' */ - eof = read_viminfo_search_pattern(virp, forceit); - |