diff options
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 125 |
1 files changed, 90 insertions, 35 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b5ca6543c5..90a564bb6a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -91,6 +91,57 @@ static char *e_auabort = N_("E855: Autocommands caused command to abort"); // Number of times free_buffer() was called. static int buf_free_count = 0; +// Read data from buffer for retrying. +static int +read_buffer( + int read_stdin, // read file from stdin, otherwise fifo + exarg_T *eap, // for forced 'ff' and 'fenc' or NULL + int flags) // extra flags for readfile() +{ + int retval = OK; + linenr_T line_count; + + // + // Read from the buffer which the text is already filled in and append at + // the end. This makes it possible to retry when 'fileformat' or + // 'fileencoding' was guessed wrong. + // + line_count = curbuf->b_ml.ml_line_count; + retval = readfile( + read_stdin ? NULL : curbuf->b_ffname, + read_stdin ? NULL : curbuf->b_fname, + (linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, + flags | READ_BUFFER); + if (retval == OK) { + // Delete the binary lines. + while (--line_count >= 0) { + ml_delete((linenr_T)1, false); + } + } else { + // Delete the converted lines. + while (curbuf->b_ml.ml_line_count > line_count) { + ml_delete(line_count, false); + } + } + // Put the cursor on the first line. + curwin->w_cursor.lnum = 1; + curwin->w_cursor.col = 0; + + if (read_stdin) { + // Set or reset 'modified' before executing autocommands, so that + // it can be changed there. + if (!readonlymode && !bufempty()) { + changed(); + } else if (retval != FAIL) { + unchanged(curbuf, false); + } + + apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, + curbuf, &retval); + } + return retval; +} + /* * Open current buffer, that is: open the memfile and read the file into * memory. @@ -106,6 +157,7 @@ open_buffer ( int retval = OK; bufref_T old_curbuf; long old_tw = curbuf->b_p_tw; + int read_fifo = false; /* * The 'readonly' flag is only set when BF_NEVERLOADED is being reset. @@ -156,13 +208,45 @@ open_buffer ( if (curbuf->b_ffname != NULL) { int old_msg_silent = msg_silent; +#ifdef UNIX + int save_bin = curbuf->b_p_bin; + int perm; + + perm = os_getperm((const char *)curbuf->b_ffname); + if (perm >= 0 && (0 +# ifdef S_ISFIFO + || S_ISFIFO(perm) +# endif +# ifdef S_ISSOCK + || S_ISSOCK(perm) +# endif +# ifdef OPEN_CHR_FILES + || (S_ISCHR(perm) + && is_dev_fd_file(curbuf->b_ffname)) +# endif + ) + ) { + read_fifo = true; + } + if (read_fifo) { + curbuf->b_p_bin = true; + } +#endif if (shortmess(SHM_FILEINFO)) { msg_silent = 1; } retval = readfile(curbuf->b_ffname, curbuf->b_fname, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_NEW); + flags | READ_NEW | (read_fifo ? READ_FIFO : 0)); +#ifdef UNIX + if (read_fifo) { + curbuf->b_p_bin = save_bin; + if (retval == OK) { + retval = read_buffer(false, eap, flags); + } + } +#endif msg_silent = old_msg_silent; // Help buffer is filtered. @@ -171,7 +255,6 @@ open_buffer ( } } else if (read_stdin) { int save_bin = curbuf->b_p_bin; - linenr_T line_count; /* * First read the text in binary mode into the buffer. @@ -185,41 +268,13 @@ open_buffer ( flags | (READ_NEW + READ_STDIN)); curbuf->b_p_bin = save_bin; if (retval == OK) { - line_count = curbuf->b_ml.ml_line_count; - retval = readfile(NULL, NULL, (linenr_T)line_count, - (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_BUFFER); - if (retval == OK) { - /* Delete the binary lines. */ - while (--line_count >= 0) - ml_delete((linenr_T)1, FALSE); - } else { - /* Delete the converted lines. */ - while (curbuf->b_ml.ml_line_count > line_count) - ml_delete(line_count, FALSE); - } - /* Put the cursor on the first line. */ - curwin->w_cursor.lnum = 1; - curwin->w_cursor.col = 0; - - // Set or reset 'modified' before executing autocommands, so that - // it can be changed there. - if (!readonlymode && !bufempty()) { - changed(); - } else if (retval == OK) { - unchanged(curbuf, false); - } - - if (retval == OK) { - apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, - curbuf, &retval); - } + retval = read_buffer(true, eap, flags); } } /* if first time loading this buffer, init b_chartab[] */ if (curbuf->b_flags & BF_NEVERLOADED) { - (void)buf_init_chartab(curbuf, FALSE); + (void)buf_init_chartab(curbuf, false); parse_cino(curbuf); } @@ -234,7 +289,7 @@ open_buffer ( || modified_was_set // ":set modified" used in autocmd || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) { changed(); - } else if (retval == OK && !read_stdin) { + } else if (retval != FAIL && !read_stdin && !read_fifo) { unchanged(curbuf, false); } save_file_ff(curbuf); // keep this fileformat @@ -416,8 +471,8 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) return; } - /* When the buffer becomes hidden, but is not unloaded, trigger - * BufHidden */ + // When the buffer becomes hidden, but is not unloaded, trigger + // BufHidden if (!unload_buf) { buf->b_locked++; if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false, |