aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/fileio.c')
-rw-r--r--src/nvim/fileio.c190
1 files changed, 103 insertions, 87 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index b2840c9402..507bf3c032 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -11,6 +11,7 @@
#include <fcntl.h>
#include "nvim/vim.h"
+#include "nvim/api/private/handle.h"
#include "nvim/ascii.h"
#include "nvim/fileio.h"
#include "nvim/buffer.h"
@@ -47,6 +48,7 @@
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/types.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -308,29 +310,30 @@ readfile (
#ifdef UNIX
int swap_mode = -1; /* protection bits for swap file */
#endif
- int fileformat = 0; /* end-of-line format */
- int keep_fileformat = FALSE;
+ int fileformat = 0; // end-of-line format
+ bool keep_fileformat = false;
+ FileInfo file_info;
int file_readonly;
linenr_T skip_count = 0;
linenr_T read_count = 0;
int msg_save = msg_scroll;
linenr_T read_no_eol_lnum = 0; // non-zero lnum when last line of
// last read was missing the eol
- int file_rewind = false;
+ bool file_rewind = false;
int can_retry;
- linenr_T conv_error = 0; /* line nr with conversion error */
- linenr_T illegal_byte = 0; /* line nr with illegal byte */
- int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
- in destination encoding */
+ linenr_T conv_error = 0; // line nr with conversion error
+ linenr_T illegal_byte = 0; // line nr with illegal byte
+ bool keep_dest_enc = false; // don't retry when char doesn't fit
+ // in destination encoding
int bad_char_behavior = BAD_REPLACE;
/* BAD_KEEP, BAD_DROP or character to
* replace with */
char_u *tmpname = NULL; /* name of 'charconvert' output file */
int fio_flags = 0;
- char_u *fenc; /* fileencoding to use */
- int fenc_alloced; /* fenc_next is in allocated memory */
- char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
- int advance_fenc = FALSE;
+ char_u *fenc; // fileencoding to use
+ bool fenc_alloced; // fenc_next is in allocated memory
+ char_u *fenc_next = NULL; // next item in 'fencs' or NULL
+ bool advance_fenc = false;
long real_size = 0;
# ifdef USE_ICONV
iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
@@ -481,7 +484,6 @@ readfile (
if (newfile && !read_stdin && !read_buffer && !read_fifo) {
// Remember time of file.
- FileInfo file_info;
if (os_fileinfo((char *)fname, &file_info)) {
buf_store_file_info(curbuf, &file_info);
curbuf->b_mtime_read = curbuf->b_mtime;
@@ -627,13 +629,30 @@ readfile (
// Set swap file protection bits after creating it.
if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
&& curbuf->b_ml.ml_mfp->mf_fname != NULL) {
- (void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname,
- (long)swap_mode);
+ const char *swap_fname = (const char *)curbuf->b_ml.ml_mfp->mf_fname;
+
+ // If the group-read bit is set but not the world-read bit, then
+ // the group must be equal to the group of the original file. If
+ // we can't make that happen then reset the group-read bit. This
+ // avoids making the swap file readable to more users when the
+ // primary group of the user is too permissive.
+ if ((swap_mode & 044) == 040) {
+ FileInfo swap_info;
+
+ if (os_fileinfo(swap_fname, &swap_info)
+ && file_info.stat.st_gid != swap_info.stat.st_gid
+ && os_fchown(curbuf->b_ml.ml_mfp->mf_fd, -1, file_info.stat.st_gid)
+ == -1) {
+ swap_mode &= 0600;
+ }
+ }
+
+ (void)os_setperm(swap_fname, swap_mode);
}
#endif
}
- /* If "Quit" selected at ATTENTION dialog, don't load the file */
+ // If "Quit" selected at ATTENTION dialog, don't load the file.
if (swap_exists_action == SEA_QUIT) {
if (!read_buffer && !read_stdin)
close(fd);
@@ -747,11 +766,11 @@ readfile (
*/
if (eap != NULL && eap->force_enc != 0) {
fenc = enc_canonize(eap->cmd + eap->force_enc);
- fenc_alloced = TRUE;
- keep_dest_enc = TRUE;
+ fenc_alloced = true;
+ keep_dest_enc = true;
} else if (curbuf->b_p_bin) {
- fenc = (char_u *)""; /* binary: don't convert */
- fenc_alloced = FALSE;
+ fenc = (char_u *)""; // binary: don't convert
+ fenc_alloced = false;
} else if (curbuf->b_help) {
// Help files are either utf-8 or latin1. Try utf-8 first, if this
// fails it must be latin1.
@@ -762,12 +781,12 @@ readfile (
fenc_alloced = false;
} else if (*p_fencs == NUL) {
- fenc = curbuf->b_p_fenc; /* use format from buffer */
- fenc_alloced = FALSE;
+ fenc = curbuf->b_p_fenc; // use format from buffer
+ fenc_alloced = false;
} else {
fenc_next = p_fencs; /* try items in 'fileencodings' */
fenc = next_fenc(&fenc_next);
- fenc_alloced = TRUE;
+ fenc_alloced = true;
}
/*
@@ -800,10 +819,11 @@ retry:
error = true;
goto failed;
}
- /* Delete the previously read lines. */
- while (lnum > from)
- ml_delete(lnum--, FALSE);
- file_rewind = FALSE;
+ // Delete the previously read lines.
+ while (lnum > from) {
+ ml_delete(lnum--, false);
+ }
+ file_rewind = false;
if (set_options) {
curbuf->b_p_bomb = FALSE;
curbuf->b_start_bomb = FALSE;
@@ -815,9 +835,9 @@ retry:
* When retrying with another "fenc" and the first time "fileformat"
* will be reset.
*/
- if (keep_fileformat)
- keep_fileformat = FALSE;
- else {
+ if (keep_fileformat) {
+ keep_fileformat = false;
+ } else {
if (eap != NULL && eap->force_ff != 0) {
fileformat = get_fileformat_force(curbuf, eap);
try_unix = try_dos = try_mac = FALSE;
@@ -841,7 +861,7 @@ retry:
/*
* Try the next entry in 'fileencodings'.
*/
- advance_fenc = FALSE;
+ advance_fenc = false;
if (eap != NULL && eap->force_enc != 0) {
/* Conversion given with "++cc=" wasn't possible, read
@@ -851,7 +871,7 @@ retry:
if (fenc_alloced)
xfree(fenc);
fenc = (char_u *)"";
- fenc_alloced = FALSE;
+ fenc_alloced = false;
} else {
if (fenc_alloced)
xfree(fenc);
@@ -860,7 +880,7 @@ retry:
fenc_alloced = (fenc_next != NULL);
} else {
fenc = (char_u *)"";
- fenc_alloced = FALSE;
+ fenc_alloced = false;
}
}
if (tmpname != NULL) {
@@ -926,8 +946,8 @@ retry:
if (tmpname == NULL) {
tmpname = readfile_charconvert(fname, fenc, &fd);
if (tmpname == NULL) {
- /* Conversion failed. Try another one. */
- advance_fenc = TRUE;
+ // Conversion failed. Try another one.
+ advance_fenc = true;
if (fd < 0) {
/* Re-opening the original file failed! */
EMSG(_("E202: Conversion made file unreadable!"));
@@ -945,7 +965,7 @@ retry:
) {
/* Conversion wanted but we can't.
* Try the next conversion in 'fileencodings' */
- advance_fenc = TRUE;
+ advance_fenc = true;
goto retry;
}
}
@@ -1180,14 +1200,14 @@ retry:
if (fio_flags == FIO_UCSBOM) {
if (ccname == NULL) {
- /* No BOM detected: retry with next encoding. */
- advance_fenc = TRUE;
+ // No BOM detected: retry with next encoding.
+ advance_fenc = true;
} else {
/* BOM detected: set "fenc" and jump back */
if (fenc_alloced)
xfree(fenc);
fenc = ccname;
- fenc_alloced = FALSE;
+ fenc_alloced = false;
}
/* retry reading without getting new bytes or rewinding */
skip_read = TRUE;
@@ -1512,9 +1532,9 @@ rewind_retry:
did_iconv = TRUE;
else
# endif
- /* use next item from 'fileencodings' */
- advance_fenc = TRUE;
- file_rewind = TRUE;
+ // use next item from 'fileencodings'
+ advance_fenc = true;
+ file_rewind = true;
goto retry;
}
}
@@ -1648,8 +1668,8 @@ rewind_retry:
fileformat = EOL_UNIX;
if (set_options)
set_fileformat(EOL_UNIX, OPT_LOCAL);
- file_rewind = TRUE;
- keep_fileformat = TRUE;
+ file_rewind = true;
+ keep_fileformat = true;
goto retry;
}
ff_error = EOL_DOS;
@@ -1760,8 +1780,8 @@ failed:
if (!recoverymode) {
/* need to delete the last line, which comes from the empty buffer */
if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY)) {
- ml_delete(curbuf->b_ml.ml_line_count, FALSE);
- --linecnt;
+ ml_delete(curbuf->b_ml.ml_line_count, false);
+ linecnt--;
}
linecnt = curbuf->b_ml.ml_line_count - linecnt;
if (filesize == 0)
@@ -4894,9 +4914,9 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
/* Copy the lines in "frombuf" to "tobuf". */
curbuf = tobuf;
- for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum) {
- p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
- if (ml_append(lnum - 1, p, 0, FALSE) == FAIL) {
+ for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
+ p = vim_strsave(ml_get_buf(frombuf, lnum, false));
+ if (ml_append(lnum - 1, p, 0, false) == FAIL) {
xfree(p);
retval = FAIL;
break;
@@ -4907,13 +4927,14 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
/* Delete all the lines in "frombuf". */
if (retval != FAIL) {
curbuf = frombuf;
- for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
- if (ml_delete(lnum, FALSE) == FAIL) {
- /* Oops! We could try putting back the saved lines, but that
- * might fail again... */
+ for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
+ if (ml_delete(lnum, false) == FAIL) {
+ // Oops! We could try putting back the saved lines, but that
+ // might fail again...
retval = FAIL;
break;
}
+ }
}
curbuf = tbuf;
@@ -6501,21 +6522,17 @@ bool check_nomodeline(char_u **argp)
return true;
}
-/*
- * Prepare for executing autocommands for (hidden) buffer "buf".
- * Search for a visible window containing the current buffer. If there isn't
- * one then use "aucmd_win".
- * Set "curbuf" and "curwin" to match "buf".
- */
-void
-aucmd_prepbuf (
- aco_save_T *aco, /* structure to save values in */
- buf_T *buf /* new curbuf */
-)
+/// Prepare for executing autocommands for (hidden) buffer `buf`.
+/// If the current buffer is not in any visible window, put it in a temporary
+/// floating window `aucmd_win`.
+/// Set `curbuf` and `curwin` to match `buf`.
+///
+/// @param aco structure to save values in
+/// @param buf new curbuf
+void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
{
- win_T *win;
- int save_ea;
- int save_acd;
+ win_T *win;
+ bool need_append = true; // Append `aucmd_win` to the window list.
/* Find a window that is for the new buffer */
if (buf == curbuf) { /* be quick when buf is curbuf */
@@ -6530,9 +6547,10 @@ aucmd_prepbuf (
}
}
- /* Allocate "aucmd_win" when needed. */
+ // Allocate the `aucmd_win` dummy floating window.
if (win == NULL && aucmd_win == NULL) {
win_alloc_aucmd_win();
+ need_append = false;
}
if (win == NULL && aucmd_win_used)
/* Strange recursive autocommand, fall back to using the current
@@ -6567,21 +6585,16 @@ aucmd_prepbuf (
aco->globaldir = globaldir;
globaldir = NULL;
-
- /* Split the current window, put the aucmd_win in the upper half.
- * We don't want the BufEnter or WinEnter autocommands. */
- block_autocmds();
- make_snapshot(SNAP_AUCMD_IDX);
- save_ea = p_ea;
- p_ea = false;
-
- /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
- save_acd = p_acd;
+ block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
+ if (need_append) {
+ win_append(lastwin, aucmd_win);
+ handle_register_window(aucmd_win);
+ win_config_float(aucmd_win, aucmd_win->w_float_config);
+ }
+ // Prevent chdir() call in win_enter_ext(), through do_autochdir()
+ int save_acd = p_acd;
p_acd = false;
-
- (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
- (void)win_comp_pos(); /* recompute window positions */
- p_ea = save_ea;
+ win_enter(aucmd_win, false);
p_acd = save_acd;
unblock_autocmds();
curwin = aucmd_win;
@@ -6597,8 +6610,6 @@ aucmd_prepbuf (
/// @param aco structure holding saved values
void aucmd_restbuf(aco_save_T *aco)
{
- int dummy;
-
if (aco->use_aucmd_win) {
curbuf->b_nwindows--;
// Find "aucmd_win", it can't be closed, but it may be in another tab page.
@@ -6617,9 +6628,14 @@ void aucmd_restbuf(aco_save_T *aco)
}
win_found:
- // Remove the window and frame from the tree of frames.
- (void)winframe_remove(curwin, &dummy, NULL);
win_remove(curwin, NULL);
+ handle_unregister_window(curwin);
+ if (curwin->w_grid.chars != NULL) {
+ ui_comp_remove_grid(&curwin->w_grid);
+ ui_call_win_hide(curwin->w_grid.handle);
+ grid_free(&curwin->w_grid);
+ }
+
aucmd_win_used = false;
last_status(false); // may need to remove last status line
@@ -6628,8 +6644,6 @@ win_found:
close_tabpage(curtab);
}
- restore_snapshot(SNAP_AUCMD_IDX, false);
- (void)win_comp_pos(); // recompute window positions
unblock_autocmds();
if (win_valid(aco->save_curwin)) {
@@ -7069,6 +7083,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
do_cmdline(NULL, getnextac, (void *)&patcmd,
DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
+ reset_lnums(); // restore cursor and topline, unless they were changed
+
if (eap != NULL) {
(void)set_cmdarg(NULL, save_cmdarg);
set_vim_var_nr(VV_CMDBANG, save_cmdbang);