blob: aa84e9bb48b8574e2a07047797edda1ba6db363a [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * fileio.c: read from and write to a file
12 */
13
Bram Moolenaar071d4272004-06-13 20:20:40 +000014#include "vim.h"
15
Bram Moolenaarf4888d02009-12-02 12:31:27 +000016#if defined(__TANDEM) || defined(__MINT__)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017# include <limits.h> /* for SSIZE_MAX */
18#endif
19
20#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
21# include <utime.h> /* for struct utimbuf */
22#endif
23
24#define BUFSIZE 8192 /* size of normal write buffer */
25#define SMBUFSIZE 256 /* size of emergency write buffer */
26
Bram Moolenaar071d4272004-06-13 20:20:40 +000027/* Is there any system that doesn't have access()? */
Bram Moolenaar9372a112005-12-06 19:59:18 +000028#define USE_MCH_ACCESS
Bram Moolenaar071d4272004-06-13 20:20:40 +000029
Bram Moolenaard25c16e2016-01-29 22:13:30 +010030static char_u *next_fenc(char_u **pp);
Bram Moolenaar13505972019-01-24 15:04:48 +010031#ifdef FEAT_EVAL
Bram Moolenaard25c16e2016-01-29 22:13:30 +010032static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000033#endif
34#ifdef FEAT_VIMINFO
Bram Moolenaard25c16e2016-01-29 22:13:30 +010035static void check_marks_read(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000036#endif
37#ifdef FEAT_CRYPT
Bram Moolenaar8767f522016-07-01 17:17:39 +020038static char_u *check_for_cryptkey(char_u *cryptkey, char_u *ptr, long *sizep, off_T *filesizep, int newfile, char_u *fname, int *did_ask);
Bram Moolenaar071d4272004-06-13 20:20:40 +000039#endif
Bram Moolenaard25c16e2016-01-29 22:13:30 +010040static int set_rw_fname(char_u *fname, char_u *sfname);
41static int msg_add_fileformat(int eol_type);
42static void msg_add_eol(void);
Bram Moolenaar8767f522016-07-01 17:17:39 +020043static int check_mtime(buf_T *buf, stat_T *s);
Bram Moolenaard25c16e2016-01-29 22:13:30 +010044static int time_differs(long t1, long t2);
Bram Moolenaard25c16e2016-01-29 22:13:30 +010045static int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap);
46static int au_find_group(char_u *name);
Bram Moolenaar70836c82006-02-20 21:28:49 +000047
Bram Moolenaar13505972019-01-24 15:04:48 +010048#define AUGROUP_DEFAULT -1 /* default autocmd group */
49#define AUGROUP_ERROR -2 /* erroneous autocmd group */
50#define AUGROUP_ALL -3 /* all autocmd groups */
Bram Moolenaar071d4272004-06-13 20:20:40 +000051
Bram Moolenaar13505972019-01-24 15:04:48 +010052#define HAS_BW_FLAGS
53#define FIO_LATIN1 0x01 /* convert Latin1 */
54#define FIO_UTF8 0x02 /* convert UTF-8 */
55#define FIO_UCS2 0x04 /* convert UCS-2 */
56#define FIO_UCS4 0x08 /* convert UCS-4 */
57#define FIO_UTF16 0x10 /* convert UTF-16 */
58#ifdef WIN3264
59# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
60# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
61# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
Bram Moolenaar071d4272004-06-13 20:20:40 +000062#endif
Bram Moolenaar13505972019-01-24 15:04:48 +010063#ifdef MACOS_CONVERT
64# define FIO_MACROMAN 0x20 /* convert MacRoman */
65#endif
66#define FIO_ENDIAN_L 0x80 /* little endian */
67#define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
68#define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
69#define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
70#define FIO_ALL -1 /* allow all formats */
Bram Moolenaar071d4272004-06-13 20:20:40 +000071
72/* When converting, a read() or write() may leave some bytes to be converted
73 * for the next call. The value is guessed... */
74#define CONV_RESTLEN 30
75
76/* We have to guess how much a sequence of bytes may expand when converting
77 * with iconv() to be able to allocate a buffer. */
78#define ICONV_MULT 8
79
80/*
81 * Structure to pass arguments from buf_write() to buf_write_bytes().
82 */
83struct bw_info
84{
85 int bw_fd; /* file descriptor */
86 char_u *bw_buf; /* buffer with data to be written */
Bram Moolenaard089d9b2007-09-30 12:02:55 +000087 int bw_len; /* length of data */
Bram Moolenaar071d4272004-06-13 20:20:40 +000088#ifdef HAS_BW_FLAGS
89 int bw_flags; /* FIO_ flags */
90#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020091#ifdef FEAT_CRYPT
92 buf_T *bw_buffer; /* buffer being written */
93#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000094 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
95 int bw_restlen; /* nr of bytes in bw_rest[] */
96 int bw_first; /* first write call */
97 char_u *bw_conv_buf; /* buffer for writing converted chars */
98 int bw_conv_buflen; /* size of bw_conv_buf */
99 int bw_conv_error; /* set for conversion error */
Bram Moolenaar32b485f2009-07-29 16:06:27 +0000100 linenr_T bw_conv_error_lnum; /* first line with error or zero */
101 linenr_T bw_start_lnum; /* line number at start of buffer */
Bram Moolenaar13505972019-01-24 15:04:48 +0100102#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104#endif
105};
106
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100107static int buf_write_bytes(struct bw_info *ip);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000108
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100109static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp);
110static int ucs2bytes(unsigned c, char_u **pp, int flags);
111static int need_conversion(char_u *fenc);
112static int get_fio_flags(char_u *ptr);
113static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags);
114static int make_bom(char_u *buf, char_u *name);
Bram Moolenaar13505972019-01-24 15:04:48 +0100115#ifdef WIN3264
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100116static int get_win_fio_flags(char_u *ptr);
Bram Moolenaar13505972019-01-24 15:04:48 +0100117#endif
118#ifdef MACOS_CONVERT
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100119static int get_mac_fio_flags(char_u *ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000120#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000121static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000122
Bram Moolenaarc3691332016-04-20 12:49:49 +0200123/*
124 * Set by the apply_autocmds_group function if the given event is equal to
125 * EVENT_FILETYPE. Used by the readfile function in order to determine if
126 * EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
127 *
128 * Relying on this value requires one to reset it prior calling
129 * apply_autocmds_group.
130 */
131static int au_did_filetype INIT(= FALSE);
Bram Moolenaarc3691332016-04-20 12:49:49 +0200132
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100134filemess(
135 buf_T *buf,
136 char_u *name,
137 char_u *s,
138 int attr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139{
140 int msg_scroll_save;
141
142 if (msg_silent != 0)
143 return;
144 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
145 /* If it's extremely long, truncate it. */
146 if (STRLEN(IObuff) > IOSIZE - 80)
147 IObuff[IOSIZE - 80] = NUL;
148 STRCAT(IObuff, s);
149 /*
150 * For the first message may have to start a new line.
151 * For further ones overwrite the previous one, reset msg_scroll before
152 * calling filemess().
153 */
154 msg_scroll_save = msg_scroll;
155 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
156 msg_scroll = FALSE;
157 if (!msg_scroll) /* wait a bit when overwriting an error msg */
158 check_for_delay(FALSE);
159 msg_start();
160 msg_scroll = msg_scroll_save;
161 msg_scrolled_ign = TRUE;
162 /* may truncate the message to avoid a hit-return prompt */
163 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
164 msg_clr_eos();
165 out_flush();
166 msg_scrolled_ign = FALSE;
167}
168
169/*
170 * Read lines from file "fname" into the buffer after line "from".
171 *
172 * 1. We allocate blocks with lalloc, as big as possible.
173 * 2. Each block is filled with characters from the file with a single read().
174 * 3. The lines are inserted in the buffer with ml_append().
175 *
176 * (caller must check that fname != NULL, unless READ_STDIN is used)
177 *
178 * "lines_to_skip" is the number of lines that must be skipped
179 * "lines_to_read" is the number of lines that are appended
180 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
181 *
182 * flags:
183 * READ_NEW starting to edit a new buffer
184 * READ_FILTER reading filter output
185 * READ_STDIN read from stdin instead of a file
186 * READ_BUFFER read from curbuf instead of a file (converting after reading
187 * stdin)
188 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
Bram Moolenaar59f931e2010-07-24 20:27:03 +0200189 * READ_KEEP_UNDO don't clear undo info or read it from a file
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200190 * READ_FIFO read from fifo/socket instead of a file
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191 *
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100192 * return FAIL for failure, NOTDONE for directory (failure), or OK
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193 */
194 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100195readfile(
196 char_u *fname,
197 char_u *sfname,
198 linenr_T from,
199 linenr_T lines_to_skip,
200 linenr_T lines_to_read,
201 exarg_T *eap, /* can be NULL! */
202 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000203{
204 int fd = 0;
205 int newfile = (flags & READ_NEW);
206 int check_readonly;
207 int filtering = (flags & READ_FILTER);
208 int read_stdin = (flags & READ_STDIN);
209 int read_buffer = (flags & READ_BUFFER);
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200210 int read_fifo = (flags & READ_FIFO);
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000211 int set_options = newfile || read_buffer
212 || (eap != NULL && eap->read_edit);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
214 colnr_T read_buf_col = 0; /* next char to read from this line */
215 char_u c;
216 linenr_T lnum = from;
217 char_u *ptr = NULL; /* pointer into read buffer */
218 char_u *buffer = NULL; /* read buffer */
219 char_u *new_buffer = NULL; /* init to shut up gcc */
220 char_u *line_start = NULL; /* init to shut up gcc */
221 int wasempty; /* buffer was empty before reading */
222 colnr_T len;
223 long size = 0;
224 char_u *p;
Bram Moolenaar8767f522016-07-01 17:17:39 +0200225 off_T filesize = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226 int skip_read = FALSE;
227#ifdef FEAT_CRYPT
228 char_u *cryptkey = NULL;
Bram Moolenaarf50a2532010-05-21 15:36:08 +0200229 int did_ask_for_key = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000230#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +0200231#ifdef FEAT_PERSISTENT_UNDO
232 context_sha256_T sha_ctx;
233 int read_undo_file = FALSE;
234#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235 int split = 0; /* number of split lines */
236#define UNKNOWN 0x0fffffff /* file size is unknown */
237 linenr_T linecnt;
238 int error = FALSE; /* errors encountered */
239 int ff_error = EOL_UNKNOWN; /* file format with errors */
240 long linerest = 0; /* remaining chars in line */
241#ifdef UNIX
242 int perm = 0;
243 int swap_mode = -1; /* protection bits for swap file */
244#else
245 int perm;
246#endif
247 int fileformat = 0; /* end-of-line format */
248 int keep_fileformat = FALSE;
Bram Moolenaar8767f522016-07-01 17:17:39 +0200249 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000250 int file_readonly;
251 linenr_T skip_count = 0;
252 linenr_T read_count = 0;
253 int msg_save = msg_scroll;
254 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
255 * last read was missing the eol */
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100256 int try_mac;
257 int try_dos;
258 int try_unix;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259 int file_rewind = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000260 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000261 linenr_T conv_error = 0; /* line nr with conversion error */
262 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
264 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000265 int bad_char_behavior = BAD_REPLACE;
266 /* BAD_KEEP, BAD_DROP or character to
267 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000268 char_u *tmpname = NULL; /* name of 'charconvert' output file */
269 int fio_flags = 0;
270 char_u *fenc; /* fileencoding to use */
271 int fenc_alloced; /* fenc_next is in allocated memory */
272 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
273 int advance_fenc = FALSE;
274 long real_size = 0;
Bram Moolenaar13505972019-01-24 15:04:48 +0100275#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +0000276 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
Bram Moolenaar13505972019-01-24 15:04:48 +0100277# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +0000278 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
279 'charconvert' next */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000280# endif
Bram Moolenaar13505972019-01-24 15:04:48 +0100281#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000282 int converted = FALSE; /* TRUE if conversion done */
283 int notconverted = FALSE; /* TRUE if conversion wanted but it
284 wasn't possible */
285 char_u conv_rest[CONV_RESTLEN];
286 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200287 buf_T *old_curbuf;
288 char_u *old_b_ffname;
289 char_u *old_b_fname;
290 int using_b_ffname;
291 int using_b_fname;
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200292
Bram Moolenaarc3691332016-04-20 12:49:49 +0200293 au_did_filetype = FALSE; /* reset before triggering any autocommands */
Bram Moolenaarc3691332016-04-20 12:49:49 +0200294
Bram Moolenaarcab35ad2011-02-15 17:39:22 +0100295 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000296
297 /*
298 * If there is no file name yet, use the one for the read file.
299 * BF_NOTEDITED is set to reflect this.
300 * Don't do this for a read from a filter.
301 * Only do this when 'cpoptions' contains the 'f' flag.
302 */
303 if (curbuf->b_ffname == NULL
304 && !filtering
305 && fname != NULL
306 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
307 && !(flags & READ_DUMMY))
308 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000309 if (set_rw_fname(fname, sfname) == FAIL)
310 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000311 }
312
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200313 /* Remember the initial values of curbuf, curbuf->b_ffname and
314 * curbuf->b_fname to detect whether they are altered as a result of
315 * executing nasty autocommands. Also check if "fname" and "sfname"
316 * point to one of these values. */
317 old_curbuf = curbuf;
318 old_b_ffname = curbuf->b_ffname;
319 old_b_fname = curbuf->b_fname;
320 using_b_ffname = (fname == curbuf->b_ffname)
321 || (sfname == curbuf->b_ffname);
322 using_b_fname = (fname == curbuf->b_fname) || (sfname == curbuf->b_fname);
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200323
Bram Moolenaardf177f62005-02-22 08:39:57 +0000324 /* After reading a file the cursor line changes but we don't want to
325 * display the line. */
326 ex_no_reprint = TRUE;
327
Bram Moolenaar55b7cf82006-09-09 12:52:42 +0000328 /* don't display the file info for another buffer now */
329 need_fileinfo = FALSE;
330
Bram Moolenaar071d4272004-06-13 20:20:40 +0000331 /*
332 * For Unix: Use the short file name whenever possible.
333 * Avoids problems with networks and when directory names are changed.
334 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
335 * another directory, which we don't detect.
336 */
337 if (sfname == NULL)
338 sfname = fname;
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200339#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000340 fname = sfname;
341#endif
342
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343 /*
344 * The BufReadCmd and FileReadCmd events intercept the reading process by
345 * executing the associated commands instead.
346 */
347 if (!filtering && !read_stdin && !read_buffer)
348 {
349 pos_T pos;
350
351 pos = curbuf->b_op_start;
352
353 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
354 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
355 curbuf->b_op_start.col = 0;
356
357 if (newfile)
358 {
359 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
360 FALSE, curbuf, eap))
361#ifdef FEAT_EVAL
362 return aborting() ? FAIL : OK;
363#else
364 return OK;
365#endif
366 }
367 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
368 FALSE, NULL, eap))
369#ifdef FEAT_EVAL
370 return aborting() ? FAIL : OK;
371#else
372 return OK;
373#endif
374
375 curbuf->b_op_start = pos;
376 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377
378 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
379 msg_scroll = FALSE; /* overwrite previous file message */
380 else
381 msg_scroll = TRUE; /* don't overwrite previous file message */
382
383 /*
384 * If the name ends in a path separator, we can't open it. Check here,
385 * because reading the file may actually work, but then creating the swap
386 * file may destroy it! Reported on MS-DOS and Win 95.
387 * If the name is too long we might crash further on, quit here.
388 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000389 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000390 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000391 p = fname + STRLEN(fname);
392 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000393 {
394 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
395 msg_end();
396 msg_scroll = msg_save;
397 return FAIL;
398 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000399 }
400
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200401 if (!read_stdin && !read_buffer && !read_fifo)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000402 {
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200403#ifdef UNIX
404 /*
405 * On Unix it is possible to read a directory, so we have to
406 * check for it before the mch_open().
407 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000408 perm = mch_getperm(fname);
409 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410 && !S_ISFIFO(perm) /* ... or fifo */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000411 && !S_ISSOCK(perm) /* ... or socket */
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +0000412# ifdef OPEN_CHR_FILES
413 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
414 /* ... or a character special file named /dev/fd/<n> */
415# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000416 )
417 {
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100418 int retval = FAIL;
419
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420 if (S_ISDIR(perm))
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100421 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000422 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100423 retval = NOTDONE;
424 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000425 else
426 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
427 msg_end();
428 msg_scroll = msg_save;
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100429 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 }
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200431#endif
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100432#if defined(MSWIN)
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000433 /*
434 * MS-Windows allows opening a device, but we will probably get stuck
435 * trying to read it.
436 */
437 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
438 {
Bram Moolenaar5386a122007-06-28 20:02:32 +0000439 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000440 msg_end();
441 msg_scroll = msg_save;
442 return FAIL;
443 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000444#endif
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200445 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000446
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200447 /* Set default or forced 'fileformat' and 'binary'. */
448 set_file_options(set_options, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449
450 /*
451 * When opening a new file we take the readonly flag from the file.
452 * Default is r/w, can be set to r/o below.
453 * Don't reset it when in readonly mode
454 * Only set/reset b_p_ro when BF_CHECK_RO is set.
455 */
456 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000457 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458 curbuf->b_p_ro = FALSE;
459
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200460 if (newfile && !read_stdin && !read_buffer && !read_fifo)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000461 {
Bram Moolenaare60acc12011-05-10 16:41:25 +0200462 /* Remember time of file. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000463 if (mch_stat((char *)fname, &st) >= 0)
464 {
465 buf_store_time(curbuf, &st, fname);
466 curbuf->b_mtime_read = curbuf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467#ifdef UNIX
468 /*
469 * Use the protection bits of the original file for the swap file.
470 * This makes it possible for others to read the name of the
471 * edited file from the swapfile, but only if they can read the
472 * edited file.
473 * Remove the "write" and "execute" bits for group and others
474 * (they must not write the swapfile).
475 * Add the "read" and "write" bits for the user, otherwise we may
476 * not be able to write to the file ourselves.
477 * Setting the bits is done below, after creating the swap file.
478 */
479 swap_mode = (st.st_mode & 0644) | 0600;
480#endif
481#ifdef FEAT_CW_EDITOR
482 /* Get the FSSpec on MacOS
483 * TODO: Update it properly when the buffer name changes
484 */
485 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
486#endif
487#ifdef VMS
488 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000489 curbuf->b_fab_rat = st.st_fab_rat;
490 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000491#endif
492 }
493 else
494 {
495 curbuf->b_mtime = 0;
496 curbuf->b_mtime_read = 0;
497 curbuf->b_orig_size = 0;
498 curbuf->b_orig_mode = 0;
499 }
500
501 /* Reset the "new file" flag. It will be set again below when the
502 * file doesn't exist. */
503 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
504 }
505
506/*
507 * for UNIX: check readonly with perm and mch_access()
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100508 * for Amiga: check readonly by trying to open the file for writing
Bram Moolenaar071d4272004-06-13 20:20:40 +0000509 */
510 file_readonly = FALSE;
511 if (read_stdin)
512 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100513#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
515 setmode(0, O_BINARY);
516#endif
517 }
518 else if (!read_buffer)
519 {
520#ifdef USE_MCH_ACCESS
521 if (
522# ifdef UNIX
523 !(perm & 0222) ||
524# endif
525 mch_access((char *)fname, W_OK))
526 file_readonly = TRUE;
527 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
528#else
529 if (!newfile
530 || readonlymode
531 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
532 {
533 file_readonly = TRUE;
534 /* try to open ro */
535 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
536 }
537#endif
538 }
539
540 if (fd < 0) /* cannot open at all */
541 {
542#ifndef UNIX
543 int isdir_f;
544#endif
545 msg_scroll = msg_save;
546#ifndef UNIX
547 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100548 * On Amiga we can't open a directory, check here.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549 */
550 isdir_f = (mch_isdir(fname));
551 perm = mch_getperm(fname); /* check if the file exists */
552 if (isdir_f)
553 {
554 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
555 curbuf->b_p_ro = TRUE; /* must use "w!" now */
556 }
557 else
558#endif
559 if (newfile)
560 {
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200561 if (perm < 0
562#ifdef ENOENT
563 && errno == ENOENT
564#endif
565 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 {
567 /*
568 * Set the 'new-file' flag, so that when the file has
569 * been created by someone else, a ":w" will complain.
570 */
571 curbuf->b_flags |= BF_NEW;
572
573 /* Create a swap file now, so that other Vims are warned
574 * that we are editing this file. Don't do this for a
575 * "nofile" or "nowrite" buffer type. */
576#ifdef FEAT_QUICKFIX
577 if (!bt_dontwrite(curbuf))
578#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000579 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000580 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000581 /* SwapExists autocommand may mess things up */
582 if (curbuf != old_curbuf
583 || (using_b_ffname
584 && (old_b_ffname != curbuf->b_ffname))
585 || (using_b_fname
586 && (old_b_fname != curbuf->b_fname)))
587 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100588 emsg(_(e_auchangedbuf));
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000589 return FAIL;
590 }
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000591 }
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000592 if (dir_of_file_exists(fname))
593 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
594 else
595 filemess(curbuf, sfname,
596 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597#ifdef FEAT_VIMINFO
598 /* Even though this is a new file, it might have been
599 * edited before and deleted. Get the old marks. */
600 check_marks_read();
601#endif
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200602 /* Set forced 'fileencoding'. */
603 if (eap != NULL)
604 set_forced_fenc(eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000605 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
606 FALSE, curbuf, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000607 /* remember the current fileformat */
608 save_file_ff(curbuf);
609
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +0100610#if defined(FEAT_EVAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000611 if (aborting()) /* autocmds may abort script processing */
612 return FAIL;
613#endif
614 return OK; /* a new file is not an error */
615 }
616 else
617 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000618 filemess(curbuf, sfname, (char_u *)(
619# ifdef EFBIG
620 (errno == EFBIG) ? _("[File too big]") :
621# endif
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200622# ifdef EOVERFLOW
623 (errno == EOVERFLOW) ? _("[File too big]") :
624# endif
Bram Moolenaar202795b2005-10-11 20:29:39 +0000625 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 curbuf->b_p_ro = TRUE; /* must use "w!" now */
627 }
628 }
629
630 return FAIL;
631 }
632
633 /*
634 * Only set the 'ro' flag for readonly files the first time they are
635 * loaded. Help files always get readonly mode
636 */
637 if ((check_readonly && file_readonly) || curbuf->b_help)
638 curbuf->b_p_ro = TRUE;
639
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000640 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000641 {
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000642 /* Don't change 'eol' if reading from buffer as it will already be
643 * correctly set when reading stdin. */
644 if (!read_buffer)
645 {
646 curbuf->b_p_eol = TRUE;
647 curbuf->b_start_eol = TRUE;
648 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000650 curbuf->b_start_bomb = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651 }
652
653 /* Create a swap file now, so that other Vims are warned that we are
654 * editing this file.
655 * Don't do this for a "nofile" or "nowrite" buffer type. */
656#ifdef FEAT_QUICKFIX
657 if (!bt_dontwrite(curbuf))
658#endif
659 {
660 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000661 if (!read_stdin && (curbuf != old_curbuf
662 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
663 || (using_b_fname && (old_b_fname != curbuf->b_fname))))
664 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100665 emsg(_(e_auchangedbuf));
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000666 if (!read_buffer)
667 close(fd);
668 return FAIL;
669 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670#ifdef UNIX
671 /* Set swap file protection bits after creating it. */
Bram Moolenaarf061e0b2009-06-24 15:32:01 +0000672 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
673 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
Bram Moolenaar5a73e0c2017-11-04 21:35:01 +0100674 {
675 char_u *swap_fname = curbuf->b_ml.ml_mfp->mf_fname;
676
677 /*
678 * If the group-read bit is set but not the world-read bit, then
679 * the group must be equal to the group of the original file. If
680 * we can't make that happen then reset the group-read bit. This
681 * avoids making the swap file readable to more users when the
682 * primary group of the user is too permissive.
683 */
684 if ((swap_mode & 044) == 040)
685 {
686 stat_T swap_st;
687
688 if (mch_stat((char *)swap_fname, &swap_st) >= 0
689 && st.st_gid != swap_st.st_gid
Bram Moolenaar02e802b2018-04-19 21:15:27 +0200690# ifdef HAVE_FCHOWN
Bram Moolenaar5a73e0c2017-11-04 21:35:01 +0100691 && fchown(curbuf->b_ml.ml_mfp->mf_fd, -1, st.st_gid)
Bram Moolenaar02e802b2018-04-19 21:15:27 +0200692 == -1
Bram Moolenaar1f131ae2018-05-21 13:39:40 +0200693# endif
Bram Moolenaar02e802b2018-04-19 21:15:27 +0200694 )
Bram Moolenaar5a73e0c2017-11-04 21:35:01 +0100695 swap_mode &= 0600;
696 }
697
698 (void)mch_setperm(swap_fname, (long)swap_mode);
699 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000700#endif
701 }
702
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000703#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704 /* If "Quit" selected at ATTENTION dialog, don't load the file */
705 if (swap_exists_action == SEA_QUIT)
706 {
707 if (!read_buffer && !read_stdin)
708 close(fd);
709 return FAIL;
710 }
711#endif
712
713 ++no_wait_return; /* don't wait for return yet */
714
715 /*
716 * Set '[ mark to the line above where the lines go (line 1 if zero).
717 */
718 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
719 curbuf->b_op_start.col = 0;
720
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100721 try_mac = (vim_strchr(p_ffs, 'm') != NULL);
722 try_dos = (vim_strchr(p_ffs, 'd') != NULL);
723 try_unix = (vim_strchr(p_ffs, 'x') != NULL);
724
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725 if (!read_buffer)
726 {
727 int m = msg_scroll;
728 int n = msg_scrolled;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729
730 /*
731 * The file must be closed again, the autocommands may want to change
732 * the file before reading it.
733 */
734 if (!read_stdin)
735 close(fd); /* ignore errors */
736
737 /*
738 * The output from the autocommands should not overwrite anything and
739 * should not be overwritten: Set msg_scroll, restore its value if no
740 * output was done.
741 */
742 msg_scroll = TRUE;
743 if (filtering)
744 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
745 FALSE, curbuf, eap);
746 else if (read_stdin)
747 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
748 FALSE, curbuf, eap);
749 else if (newfile)
750 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
751 FALSE, curbuf, eap);
752 else
753 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
754 FALSE, NULL, eap);
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100755 /* autocommands may have changed it */
756 try_mac = (vim_strchr(p_ffs, 'm') != NULL);
757 try_dos = (vim_strchr(p_ffs, 'd') != NULL);
758 try_unix = (vim_strchr(p_ffs, 'x') != NULL);
759
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 if (msg_scrolled == n)
761 msg_scroll = m;
762
763#ifdef FEAT_EVAL
764 if (aborting()) /* autocmds may abort script processing */
765 {
766 --no_wait_return;
767 msg_scroll = msg_save;
768 curbuf->b_p_ro = TRUE; /* must use "w!" now */
769 return FAIL;
770 }
771#endif
772 /*
773 * Don't allow the autocommands to change the current buffer.
774 * Try to re-open the file.
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000775 *
776 * Don't allow the autocommands to change the buffer name either
777 * (cd for example) if it invalidates fname or sfname.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000778 */
779 if (!read_stdin && (curbuf != old_curbuf
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000780 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
781 || (using_b_fname && (old_b_fname != curbuf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
783 {
784 --no_wait_return;
785 msg_scroll = msg_save;
786 if (fd < 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100787 emsg(_("E200: *ReadPre autocommands made the file unreadable"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100789 emsg(_("E201: *ReadPre autocommands must not change current buffer"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790 curbuf->b_p_ro = TRUE; /* must use "w!" now */
791 return FAIL;
792 }
793 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000794
795 /* Autocommands may add lines to the file, need to check if it is empty */
796 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
797
798 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
799 {
800 /*
801 * Show the user that we are busy reading the input. Sometimes this
802 * may take a while. When reading from stdin another program may
803 * still be running, don't move the cursor to the last line, unless
804 * always using the GUI.
805 */
806 if (read_stdin)
807 {
Bram Moolenaar234d1622017-11-18 14:55:23 +0100808 if (!is_not_a_term())
809 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810#ifndef ALWAYS_USE_GUI
Bram Moolenaar234d1622017-11-18 14:55:23 +0100811 mch_msg(_("Vim: Reading from stdin...\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812#endif
813#ifdef FEAT_GUI
Bram Moolenaar234d1622017-11-18 14:55:23 +0100814 /* Also write a message in the GUI window, if there is one. */
815 if (gui.in_use && !gui.dying && !gui.starting)
816 {
817 p = (char_u *)_("Reading from stdin...");
818 gui_write(p, (int)STRLEN(p));
819 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820#endif
Bram Moolenaar234d1622017-11-18 14:55:23 +0100821 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822 }
823 else if (!read_buffer)
824 filemess(curbuf, sfname, (char_u *)"", 0);
825 }
826
827 msg_scroll = FALSE; /* overwrite the file message */
828
829 /*
830 * Set linecnt now, before the "retry" caused by a wrong guess for
831 * fileformat, and after the autocommands, which may change them.
832 */
833 linecnt = curbuf->b_ml.ml_line_count;
834
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000835 /* "++bad=" argument. */
836 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000837 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000838 bad_char_behavior = eap->bad_char;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000839 if (set_options)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000840 curbuf->b_bad_char = eap->bad_char;
841 }
842 else
843 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000844
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000846 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 */
848 if (eap != NULL && eap->force_enc != 0)
849 {
850 fenc = enc_canonize(eap->cmd + eap->force_enc);
851 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000852 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853 }
854 else if (curbuf->b_p_bin)
855 {
856 fenc = (char_u *)""; /* binary: don't convert */
857 fenc_alloced = FALSE;
858 }
859 else if (curbuf->b_help)
860 {
861 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000862 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863
864 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
865 * fails it must be latin1.
866 * Always do this when 'encoding' is "utf-8". Otherwise only do
867 * this when needed to avoid [converted] remarks all the time.
868 * It is needed when the first line contains non-ASCII characters.
869 * That is only in *.??x files. */
870 fenc = (char_u *)"latin1";
871 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000872 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000874 fc = fname[STRLEN(fname) - 1];
875 if (TOLOWER_ASC(fc) == 'x')
876 {
877 /* Read the first line (and a bit more). Immediately rewind to
878 * the start of the file. If the read() fails "len" is -1. */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +0100879 len = read_eintr(fd, firstline, 80);
Bram Moolenaar8767f522016-07-01 17:17:39 +0200880 vim_lseek(fd, (off_T)0L, SEEK_SET);
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000881 for (p = firstline; p < firstline + len; ++p)
882 if (*p >= 0x80)
883 {
884 c = TRUE;
885 break;
886 }
887 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 }
889
890 if (c)
891 {
892 fenc_next = fenc;
893 fenc = (char_u *)"utf-8";
894
895 /* When the file is utf-8 but a character doesn't fit in
896 * 'encoding' don't retry. In help text editing utf-8 bytes
897 * doesn't make sense. */
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000898 if (!enc_utf8)
899 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000900 }
901 fenc_alloced = FALSE;
902 }
903 else if (*p_fencs == NUL)
904 {
905 fenc = curbuf->b_p_fenc; /* use format from buffer */
906 fenc_alloced = FALSE;
907 }
908 else
909 {
910 fenc_next = p_fencs; /* try items in 'fileencodings' */
911 fenc = next_fenc(&fenc_next);
912 fenc_alloced = TRUE;
913 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914
915 /*
916 * Jump back here to retry reading the file in different ways.
917 * Reasons to retry:
918 * - encoding conversion failed: try another one from "fenc_next"
919 * - BOM detected and fenc was set, need to setup conversion
920 * - "fileformat" check failed: try another
921 *
922 * Variables set for special retry actions:
923 * "file_rewind" Rewind the file to start reading it again.
924 * "advance_fenc" Advance "fenc" using "fenc_next".
925 * "skip_read" Re-use already read bytes (BOM detected).
926 * "did_iconv" iconv() conversion failed, try 'charconvert'.
927 * "keep_fileformat" Don't reset "fileformat".
928 *
929 * Other status indicators:
930 * "tmpname" When != NULL did conversion with 'charconvert'.
931 * Output file has to be deleted afterwards.
932 * "iconv_fd" When != -1 did conversion with iconv().
933 */
934retry:
935
936 if (file_rewind)
937 {
938 if (read_buffer)
939 {
940 read_buf_lnum = 1;
941 read_buf_col = 0;
942 }
Bram Moolenaar8767f522016-07-01 17:17:39 +0200943 else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000944 {
945 /* Can't rewind the file, give up. */
946 error = TRUE;
947 goto failed;
948 }
949 /* Delete the previously read lines. */
950 while (lnum > from)
951 ml_delete(lnum--, FALSE);
952 file_rewind = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000953 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000954 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000955 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000956 curbuf->b_start_bomb = FALSE;
957 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000958 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 }
960
961 /*
962 * When retrying with another "fenc" and the first time "fileformat"
963 * will be reset.
964 */
965 if (keep_fileformat)
966 keep_fileformat = FALSE;
967 else
968 {
969 if (eap != NULL && eap->force_ff != 0)
Bram Moolenaar1c860362008-11-12 15:05:21 +0000970 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000971 fileformat = get_fileformat_force(curbuf, eap);
Bram Moolenaar1c860362008-11-12 15:05:21 +0000972 try_unix = try_dos = try_mac = FALSE;
973 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 else if (curbuf->b_p_bin)
975 fileformat = EOL_UNIX; /* binary: use Unix format */
976 else if (*p_ffs == NUL)
977 fileformat = get_fileformat(curbuf);/* use format from buffer */
978 else
979 fileformat = EOL_UNKNOWN; /* detect from file */
980 }
981
Bram Moolenaar13505972019-01-24 15:04:48 +0100982#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 if (iconv_fd != (iconv_t)-1)
984 {
985 /* aborted conversion with iconv(), close the descriptor */
986 iconv_close(iconv_fd);
987 iconv_fd = (iconv_t)-1;
988 }
Bram Moolenaar13505972019-01-24 15:04:48 +0100989#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990
991 if (advance_fenc)
992 {
993 /*
994 * Try the next entry in 'fileencodings'.
995 */
996 advance_fenc = FALSE;
997
998 if (eap != NULL && eap->force_enc != 0)
999 {
1000 /* Conversion given with "++cc=" wasn't possible, read
1001 * without conversion. */
1002 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001003 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004 if (fenc_alloced)
1005 vim_free(fenc);
1006 fenc = (char_u *)"";
1007 fenc_alloced = FALSE;
1008 }
1009 else
1010 {
1011 if (fenc_alloced)
1012 vim_free(fenc);
1013 if (fenc_next != NULL)
1014 {
1015 fenc = next_fenc(&fenc_next);
1016 fenc_alloced = (fenc_next != NULL);
1017 }
1018 else
1019 {
1020 fenc = (char_u *)"";
1021 fenc_alloced = FALSE;
1022 }
1023 }
1024 if (tmpname != NULL)
1025 {
1026 mch_remove(tmpname); /* delete converted file */
Bram Moolenaard23a8232018-02-10 18:45:26 +01001027 VIM_CLEAR(tmpname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 }
1029 }
1030
1031 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001032 * Conversion may be required when the encoding of the file is different
1033 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034 */
1035 fio_flags = 0;
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001036 converted = need_conversion(fenc);
1037 if (converted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001038 {
1039
1040 /* "ucs-bom" means we need to check the first bytes of the file
1041 * for a BOM. */
1042 if (STRCMP(fenc, ENC_UCSBOM) == 0)
1043 fio_flags = FIO_UCSBOM;
1044
1045 /*
1046 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
1047 * done. This is handled below after read(). Prepare the
1048 * fio_flags to avoid having to parse the string each time.
1049 * Also check for Unicode to Latin1 conversion, because iconv()
1050 * appears not to handle this correctly. This works just like
1051 * conversion to UTF-8 except how the resulting character is put in
1052 * the buffer.
1053 */
1054 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
1055 fio_flags = get_fio_flags(fenc);
1056
Bram Moolenaar13505972019-01-24 15:04:48 +01001057#ifdef WIN3264
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 /*
1059 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
1060 * is handled with MultiByteToWideChar().
1061 */
1062 if (fio_flags == 0)
1063 fio_flags = get_win_fio_flags(fenc);
Bram Moolenaar13505972019-01-24 15:04:48 +01001064#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065
Bram Moolenaar13505972019-01-24 15:04:48 +01001066#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
1068 if (fio_flags == 0)
1069 fio_flags = get_mac_fio_flags(fenc);
Bram Moolenaar13505972019-01-24 15:04:48 +01001070#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001071
Bram Moolenaar13505972019-01-24 15:04:48 +01001072#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001073 /*
1074 * Try using iconv() if we can't convert internally.
1075 */
1076 if (fio_flags == 0
Bram Moolenaar13505972019-01-24 15:04:48 +01001077# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078 && !did_iconv
Bram Moolenaar13505972019-01-24 15:04:48 +01001079# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080 )
1081 iconv_fd = (iconv_t)my_iconv_open(
1082 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
Bram Moolenaar13505972019-01-24 15:04:48 +01001083#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084
Bram Moolenaar13505972019-01-24 15:04:48 +01001085#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086 /*
1087 * Use the 'charconvert' expression when conversion is required
1088 * and we can't do it internally or with iconv().
1089 */
1090 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001091 && !read_fifo
Bram Moolenaar13505972019-01-24 15:04:48 +01001092# ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093 && iconv_fd == (iconv_t)-1
Bram Moolenaar13505972019-01-24 15:04:48 +01001094# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 )
1096 {
Bram Moolenaar13505972019-01-24 15:04:48 +01001097# ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001098 did_iconv = FALSE;
Bram Moolenaar13505972019-01-24 15:04:48 +01001099# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100 /* Skip conversion when it's already done (retry for wrong
1101 * "fileformat"). */
1102 if (tmpname == NULL)
1103 {
1104 tmpname = readfile_charconvert(fname, fenc, &fd);
1105 if (tmpname == NULL)
1106 {
1107 /* Conversion failed. Try another one. */
1108 advance_fenc = TRUE;
1109 if (fd < 0)
1110 {
1111 /* Re-opening the original file failed! */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001112 emsg(_("E202: Conversion made file unreadable!"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001113 error = TRUE;
1114 goto failed;
1115 }
1116 goto retry;
1117 }
1118 }
1119 }
1120 else
Bram Moolenaar13505972019-01-24 15:04:48 +01001121#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001122 {
1123 if (fio_flags == 0
Bram Moolenaar13505972019-01-24 15:04:48 +01001124#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001125 && iconv_fd == (iconv_t)-1
Bram Moolenaar13505972019-01-24 15:04:48 +01001126#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001127 )
1128 {
1129 /* Conversion wanted but we can't.
1130 * Try the next conversion in 'fileencodings' */
1131 advance_fenc = TRUE;
1132 goto retry;
1133 }
1134 }
1135 }
1136
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001137 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001139 * stdin or fixed at a specific encoding. */
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001140 can_retry = (*fenc != NUL && !read_stdin && !read_fifo && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141
1142 if (!skip_read)
1143 {
1144 linerest = 0;
1145 filesize = 0;
1146 skip_count = lines_to_skip;
1147 read_count = lines_to_read;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001148 conv_restlen = 0;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001149#ifdef FEAT_PERSISTENT_UNDO
Bram Moolenaar59f931e2010-07-24 20:27:03 +02001150 read_undo_file = (newfile && (flags & READ_KEEP_UNDO) == 0
1151 && curbuf->b_ffname != NULL
1152 && curbuf->b_p_udf
1153 && !filtering
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001154 && !read_fifo
Bram Moolenaar59f931e2010-07-24 20:27:03 +02001155 && !read_stdin
1156 && !read_buffer);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001157 if (read_undo_file)
1158 sha256_start(&sha_ctx);
1159#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001160#ifdef FEAT_CRYPT
1161 if (curbuf->b_cryptstate != NULL)
1162 {
1163 /* Need to free the state, but keep the key, don't want to ask for
1164 * it again. */
1165 crypt_free_state(curbuf->b_cryptstate);
1166 curbuf->b_cryptstate = NULL;
1167 }
1168#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169 }
1170
1171 while (!error && !got_int)
1172 {
1173 /*
1174 * We allocate as much space for the file as we can get, plus
1175 * space for the old line plus room for one terminating NUL.
1176 * The amount is limited by the fact that read() only can read
1177 * upto max_unsigned characters (and other things).
1178 */
Bram Moolenaar13d3b052018-04-29 13:34:47 +02001179 if (!skip_read)
1180 {
1181#if VIM_SIZEOF_INT > 2
1182# if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
1183 size = SSIZE_MAX; /* use max I/O size, 52K */
1184# else
1185 /* Use buffer >= 64K. Add linerest to double the size if the
1186 * line gets very long, to avoid a lot of copying. But don't
1187 * read more than 1 Mbyte at a time, so we can be interrupted.
1188 */
1189 size = 0x10000L + linerest;
1190 if (size > 0x100000L)
1191 size = 0x100000L;
1192# endif
1193#else
1194 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1195#endif
1196 }
1197
1198 /* Protect against the argument of lalloc() going negative. */
1199 if (
Bram Moolenaara2aa31a2014-02-23 22:52:40 +01001200#if VIM_SIZEOF_INT <= 2
Bram Moolenaar13d3b052018-04-29 13:34:47 +02001201 linerest >= 0x7ff0
1202#else
1203 size < 0 || size + linerest + 1 < 0 || linerest >= MAXCOL
1204#endif
1205 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 {
1207 ++split;
1208 *ptr = NL; /* split line by inserting a NL */
1209 size = 1;
1210 }
1211 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212 {
1213 if (!skip_read)
1214 {
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001215 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001216 {
1217 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1218 FALSE)) != NULL)
1219 break;
1220 }
1221 if (new_buffer == NULL)
1222 {
1223 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1224 error = TRUE;
1225 break;
1226 }
1227 if (linerest) /* copy characters from the previous buffer */
1228 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1229 vim_free(buffer);
1230 buffer = new_buffer;
1231 ptr = buffer + linerest;
1232 line_start = buffer;
1233
Bram Moolenaar071d4272004-06-13 20:20:40 +00001234 /* May need room to translate into.
1235 * For iconv() we don't really know the required space, use a
1236 * factor ICONV_MULT.
1237 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1238 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1239 * become up to 4 bytes, size must be multiple of 2
1240 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1241 * multiple of 2
1242 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1243 * multiple of 4 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001244 real_size = (int)size;
Bram Moolenaar13505972019-01-24 15:04:48 +01001245#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001246 if (iconv_fd != (iconv_t)-1)
1247 size = size / ICONV_MULT;
1248 else
Bram Moolenaar13505972019-01-24 15:04:48 +01001249#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250 if (fio_flags & FIO_LATIN1)
1251 size = size / 2;
1252 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1253 size = (size * 2 / 3) & ~1;
1254 else if (fio_flags & FIO_UCS4)
1255 size = (size * 2 / 3) & ~3;
1256 else if (fio_flags == FIO_UCSBOM)
1257 size = size / ICONV_MULT; /* worst case */
Bram Moolenaar13505972019-01-24 15:04:48 +01001258#ifdef WIN3264
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 else if (fio_flags & FIO_CODEPAGE)
1260 size = size / ICONV_MULT; /* also worst case */
Bram Moolenaar13505972019-01-24 15:04:48 +01001261#endif
1262#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001263 else if (fio_flags & FIO_MACROMAN)
1264 size = size / ICONV_MULT; /* also worst case */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001265#endif
1266
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267 if (conv_restlen > 0)
1268 {
1269 /* Insert unconverted bytes from previous line. */
1270 mch_memmove(ptr, conv_rest, conv_restlen);
1271 ptr += conv_restlen;
1272 size -= conv_restlen;
1273 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274
1275 if (read_buffer)
1276 {
1277 /*
1278 * Read bytes from curbuf. Used for converting text read
1279 * from stdin.
1280 */
1281 if (read_buf_lnum > from)
1282 size = 0;
1283 else
1284 {
1285 int n, ni;
1286 long tlen;
1287
1288 tlen = 0;
1289 for (;;)
1290 {
1291 p = ml_get(read_buf_lnum) + read_buf_col;
1292 n = (int)STRLEN(p);
1293 if ((int)tlen + n + 1 > size)
1294 {
1295 /* Filled up to "size", append partial line.
1296 * Change NL to NUL to reverse the effect done
1297 * below. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001298 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001299 for (ni = 0; ni < n; ++ni)
1300 {
1301 if (p[ni] == NL)
1302 ptr[tlen++] = NUL;
1303 else
1304 ptr[tlen++] = p[ni];
1305 }
1306 read_buf_col += n;
1307 break;
1308 }
1309 else
1310 {
1311 /* Append whole line and new-line. Change NL
1312 * to NUL to reverse the effect done below. */
1313 for (ni = 0; ni < n; ++ni)
1314 {
1315 if (p[ni] == NL)
1316 ptr[tlen++] = NUL;
1317 else
1318 ptr[tlen++] = p[ni];
1319 }
1320 ptr[tlen++] = NL;
1321 read_buf_col = 0;
1322 if (++read_buf_lnum > from)
1323 {
1324 /* When the last line didn't have an
1325 * end-of-line don't add it now either. */
1326 if (!curbuf->b_p_eol)
1327 --tlen;
1328 size = tlen;
1329 break;
1330 }
1331 }
1332 }
1333 }
1334 }
1335 else
1336 {
1337 /*
1338 * Read bytes from the file.
1339 */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01001340 size = read_eintr(fd, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001341 }
1342
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001343#ifdef FEAT_CRYPT
1344 /*
1345 * At start of file: Check for magic number of encryption.
1346 */
1347 if (filesize == 0 && size > 0)
1348 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
1349 &filesize, newfile, sfname,
1350 &did_ask_for_key);
1351 /*
1352 * Decrypt the read bytes. This is done before checking for
1353 * EOF because the crypt layer may be buffering.
1354 */
Bram Moolenaar829aa642017-08-23 22:32:35 +02001355 if (cryptkey != NULL && curbuf->b_cryptstate != NULL
1356 && size > 0)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001357 {
Bram Moolenaar987411d2019-01-18 22:48:34 +01001358# ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001359 if (crypt_works_inplace(curbuf->b_cryptstate))
1360 {
Bram Moolenaar987411d2019-01-18 22:48:34 +01001361# endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001362 crypt_decode_inplace(curbuf->b_cryptstate, ptr, size);
Bram Moolenaar987411d2019-01-18 22:48:34 +01001363# ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001364 }
1365 else
1366 {
1367 char_u *newptr = NULL;
1368 int decrypted_size;
1369
1370 decrypted_size = crypt_decode_alloc(
1371 curbuf->b_cryptstate, ptr, size, &newptr);
1372
1373 /* If the crypt layer is buffering, not producing
1374 * anything yet, need to read more. */
Bram Moolenaar1c17ffa2018-04-24 15:19:04 +02001375 if (decrypted_size == 0)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001376 continue;
1377
1378 if (linerest == 0)
1379 {
1380 /* Simple case: reuse returned buffer (may be
1381 * NULL, checked later). */
1382 new_buffer = newptr;
1383 }
1384 else
1385 {
1386 long_u new_size;
1387
1388 /* Need new buffer to add bytes carried over. */
1389 new_size = (long_u)(decrypted_size + linerest + 1);
1390 new_buffer = lalloc(new_size, FALSE);
1391 if (new_buffer == NULL)
1392 {
1393 do_outofmem_msg(new_size);
1394 error = TRUE;
1395 break;
1396 }
1397
1398 mch_memmove(new_buffer, buffer, linerest);
1399 if (newptr != NULL)
1400 mch_memmove(new_buffer + linerest, newptr,
1401 decrypted_size);
1402 }
1403
1404 if (new_buffer != NULL)
1405 {
1406 vim_free(buffer);
1407 buffer = new_buffer;
1408 new_buffer = NULL;
1409 line_start = buffer;
1410 ptr = buffer + linerest;
1411 }
1412 size = decrypted_size;
1413 }
Bram Moolenaar987411d2019-01-18 22:48:34 +01001414# endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001415 }
1416#endif
1417
Bram Moolenaar071d4272004-06-13 20:20:40 +00001418 if (size <= 0)
1419 {
1420 if (size < 0) /* read error */
1421 error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001422 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001423 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001424 /*
1425 * Reached end-of-file but some trailing bytes could
1426 * not be converted. Truncated file?
1427 */
1428
1429 /* When we did a conversion report an error. */
1430 if (fio_flags != 0
Bram Moolenaar13505972019-01-24 15:04:48 +01001431#ifdef USE_ICONV
Bram Moolenaarf453d352008-06-04 17:37:34 +00001432 || iconv_fd != (iconv_t)-1
Bram Moolenaar13505972019-01-24 15:04:48 +01001433#endif
Bram Moolenaarf453d352008-06-04 17:37:34 +00001434 )
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001435 {
Bram Moolenaare8d95302013-04-24 16:34:02 +02001436 if (can_retry)
1437 goto rewind_retry;
Bram Moolenaarf453d352008-06-04 17:37:34 +00001438 if (conv_error == 0)
1439 conv_error = curbuf->b_ml.ml_line_count
1440 - linecnt + 1;
1441 }
1442 /* Remember the first linenr with an illegal byte */
1443 else if (illegal_byte == 0)
1444 illegal_byte = curbuf->b_ml.ml_line_count
1445 - linecnt + 1;
1446 if (bad_char_behavior == BAD_DROP)
1447 {
1448 *(ptr - conv_restlen) = NUL;
1449 conv_restlen = 0;
1450 }
1451 else
1452 {
1453 /* Replace the trailing bytes with the replacement
1454 * character if we were converting; if we weren't,
1455 * leave the UTF8 checking code to do it, as it
1456 * works slightly differently. */
1457 if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
Bram Moolenaar13505972019-01-24 15:04:48 +01001458#ifdef USE_ICONV
Bram Moolenaarf453d352008-06-04 17:37:34 +00001459 || iconv_fd != (iconv_t)-1
Bram Moolenaar13505972019-01-24 15:04:48 +01001460#endif
Bram Moolenaarf453d352008-06-04 17:37:34 +00001461 ))
1462 {
1463 while (conv_restlen > 0)
1464 {
1465 *(--ptr) = bad_char_behavior;
1466 --conv_restlen;
1467 }
1468 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001469 fio_flags = 0; /* don't convert this */
Bram Moolenaar13505972019-01-24 15:04:48 +01001470#ifdef USE_ICONV
Bram Moolenaarb21e5842006-04-16 18:30:08 +00001471 if (iconv_fd != (iconv_t)-1)
1472 {
1473 iconv_close(iconv_fd);
1474 iconv_fd = (iconv_t)-1;
1475 }
Bram Moolenaar13505972019-01-24 15:04:48 +01001476#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001477 }
1478 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001479 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480 }
1481 skip_read = FALSE;
1482
Bram Moolenaar071d4272004-06-13 20:20:40 +00001483 /*
1484 * At start of file (or after crypt magic number): Check for BOM.
1485 * Also check for a BOM for other Unicode encodings, but not after
1486 * converting with 'charconvert' or when a BOM has already been
1487 * found.
1488 */
1489 if ((filesize == 0
Bram Moolenaar13505972019-01-24 15:04:48 +01001490#ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001491 || (cryptkey != NULL
1492 && filesize == crypt_get_header_len(
1493 crypt_get_method_nr(curbuf)))
Bram Moolenaar13505972019-01-24 15:04:48 +01001494#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001495 )
1496 && (fio_flags == FIO_UCSBOM
1497 || (!curbuf->b_p_bomb
1498 && tmpname == NULL
1499 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1500 {
1501 char_u *ccname;
1502 int blen;
1503
1504 /* no BOM detection in a short file or in binary mode */
1505 if (size < 2 || curbuf->b_p_bin)
1506 ccname = NULL;
1507 else
1508 ccname = check_for_bom(ptr, size, &blen,
1509 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1510 if (ccname != NULL)
1511 {
1512 /* Remove BOM from the text */
1513 filesize += blen;
1514 size -= blen;
1515 mch_memmove(ptr, ptr + blen, (size_t)size);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001516 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001517 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001518 curbuf->b_p_bomb = TRUE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001519 curbuf->b_start_bomb = TRUE;
1520 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001521 }
1522
1523 if (fio_flags == FIO_UCSBOM)
1524 {
1525 if (ccname == NULL)
1526 {
1527 /* No BOM detected: retry with next encoding. */
1528 advance_fenc = TRUE;
1529 }
1530 else
1531 {
1532 /* BOM detected: set "fenc" and jump back */
1533 if (fenc_alloced)
1534 vim_free(fenc);
1535 fenc = ccname;
1536 fenc_alloced = FALSE;
1537 }
1538 /* retry reading without getting new bytes or rewinding */
1539 skip_read = TRUE;
1540 goto retry;
1541 }
1542 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00001543
1544 /* Include not converted bytes. */
1545 ptr -= conv_restlen;
1546 size += conv_restlen;
1547 conv_restlen = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001548 /*
1549 * Break here for a read error or end-of-file.
1550 */
1551 if (size <= 0)
1552 break;
1553
Bram Moolenaar071d4272004-06-13 20:20:40 +00001554
Bram Moolenaar13505972019-01-24 15:04:48 +01001555#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00001556 if (iconv_fd != (iconv_t)-1)
1557 {
1558 /*
1559 * Attempt conversion of the read bytes to 'encoding' using
1560 * iconv().
1561 */
1562 const char *fromp;
1563 char *top;
1564 size_t from_size;
1565 size_t to_size;
1566
1567 fromp = (char *)ptr;
1568 from_size = size;
1569 ptr += size;
1570 top = (char *)ptr;
1571 to_size = real_size - size;
1572
1573 /*
1574 * If there is conversion error or not enough room try using
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001575 * another conversion. Except for when there is no
1576 * alternative (help files).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001577 */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001578 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1579 &top, &to_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001580 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1581 || from_size > CONV_RESTLEN)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001582 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001583 if (can_retry)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001584 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001585 if (conv_error == 0)
1586 conv_error = readfile_linenr(linecnt,
1587 ptr, (char_u *)top);
Bram Moolenaar42eeac32005-06-29 22:40:58 +00001588
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001589 /* Deal with a bad byte and continue with the next. */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001590 ++fromp;
1591 --from_size;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001592 if (bad_char_behavior == BAD_KEEP)
1593 {
1594 *top++ = *(fromp - 1);
1595 --to_size;
1596 }
1597 else if (bad_char_behavior != BAD_DROP)
1598 {
1599 *top++ = bad_char_behavior;
1600 --to_size;
1601 }
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001602 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001603
1604 if (from_size > 0)
1605 {
1606 /* Some remaining characters, keep them for the next
1607 * round. */
1608 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1609 conv_restlen = (int)from_size;
1610 }
1611
1612 /* move the linerest to before the converted characters */
1613 line_start = ptr - linerest;
1614 mch_memmove(line_start, buffer, (size_t)linerest);
1615 size = (long)((char_u *)top - ptr);
1616 }
Bram Moolenaar13505972019-01-24 15:04:48 +01001617#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001618
Bram Moolenaar13505972019-01-24 15:04:48 +01001619#ifdef WIN3264
Bram Moolenaar071d4272004-06-13 20:20:40 +00001620 if (fio_flags & FIO_CODEPAGE)
1621 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001622 char_u *src, *dst;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001623 WCHAR ucs2buf[3];
1624 int ucs2len;
1625 int codepage = FIO_GET_CP(fio_flags);
1626 int bytelen;
1627 int found_bad;
1628 char replstr[2];
1629
Bram Moolenaar071d4272004-06-13 20:20:40 +00001630 /*
1631 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001632 * a codepage, using standard MS-Windows functions. This
1633 * requires two steps:
1634 * 1. convert from 'fileencoding' to ucs-2
1635 * 2. convert from ucs-2 to 'encoding'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001636 *
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001637 * Because there may be illegal bytes AND an incomplete byte
1638 * sequence at the end, we may have to do the conversion one
1639 * character at a time to get it right.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001640 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001642 /* Replacement string for WideCharToMultiByte(). */
1643 if (bad_char_behavior > 0)
1644 replstr[0] = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001645 else
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001646 replstr[0] = '?';
1647 replstr[1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001648
1649 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001650 * Move the bytes to the end of the buffer, so that we have
1651 * room to put the result at the start.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001652 */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001653 src = ptr + real_size - size;
1654 mch_memmove(src, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001655
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001656 /*
1657 * Do the conversion.
1658 */
1659 dst = ptr;
1660 size = size;
1661 while (size > 0)
1662 {
1663 found_bad = FALSE;
1664
1665# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1666 if (codepage == CP_UTF8)
1667 {
1668 /* Handle CP_UTF8 input ourselves to be able to handle
1669 * trailing bytes properly.
1670 * Get one UTF-8 character from src. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001671 bytelen = (int)utf_ptr2len_len(src, size);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001672 if (bytelen > size)
1673 {
1674 /* Only got some bytes of a character. Normally
1675 * it's put in "conv_rest", but if it's too long
1676 * deal with it as if they were illegal bytes. */
1677 if (bytelen <= CONV_RESTLEN)
1678 break;
1679
1680 /* weird overlong byte sequence */
1681 bytelen = size;
1682 found_bad = TRUE;
1683 }
1684 else
1685 {
Bram Moolenaarc01140a2006-03-24 22:21:52 +00001686 int u8c = utf_ptr2char(src);
1687
Bram Moolenaar86e01082005-12-29 22:45:34 +00001688 if (u8c > 0xffff || (*src >= 0x80 && bytelen == 1))
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001689 found_bad = TRUE;
1690 ucs2buf[0] = u8c;
1691 ucs2len = 1;
1692 }
1693 }
1694 else
1695# endif
1696 {
1697 /* We don't know how long the byte sequence is, try
1698 * from one to three bytes. */
1699 for (bytelen = 1; bytelen <= size && bytelen <= 3;
1700 ++bytelen)
1701 {
1702 ucs2len = MultiByteToWideChar(codepage,
1703 MB_ERR_INVALID_CHARS,
1704 (LPCSTR)src, bytelen,
1705 ucs2buf, 3);
1706 if (ucs2len > 0)
1707 break;
1708 }
1709 if (ucs2len == 0)
1710 {
1711 /* If we have only one byte then it's probably an
1712 * incomplete byte sequence. Otherwise discard
1713 * one byte as a bad character. */
1714 if (size == 1)
1715 break;
1716 found_bad = TRUE;
1717 bytelen = 1;
1718 }
1719 }
1720
1721 if (!found_bad)
1722 {
1723 int i;
1724
1725 /* Convert "ucs2buf[ucs2len]" to 'enc' in "dst". */
1726 if (enc_utf8)
1727 {
1728 /* From UCS-2 to UTF-8. Cannot fail. */
1729 for (i = 0; i < ucs2len; ++i)
1730 dst += utf_char2bytes(ucs2buf[i], dst);
1731 }
1732 else
1733 {
1734 BOOL bad = FALSE;
1735 int dstlen;
1736
1737 /* From UCS-2 to "enc_codepage". If the
1738 * conversion uses the default character "?",
1739 * the data doesn't fit in this encoding. */
1740 dstlen = WideCharToMultiByte(enc_codepage, 0,
1741 (LPCWSTR)ucs2buf, ucs2len,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001742 (LPSTR)dst, (int)(src - dst),
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001743 replstr, &bad);
1744 if (bad)
1745 found_bad = TRUE;
1746 else
1747 dst += dstlen;
1748 }
1749 }
1750
1751 if (found_bad)
1752 {
1753 /* Deal with bytes we can't convert. */
1754 if (can_retry)
1755 goto rewind_retry;
1756 if (conv_error == 0)
1757 conv_error = readfile_linenr(linecnt, ptr, dst);
1758 if (bad_char_behavior != BAD_DROP)
1759 {
1760 if (bad_char_behavior == BAD_KEEP)
1761 {
1762 mch_memmove(dst, src, bytelen);
1763 dst += bytelen;
1764 }
1765 else
1766 *dst++ = bad_char_behavior;
1767 }
1768 }
1769
1770 src += bytelen;
1771 size -= bytelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001772 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001773
1774 if (size > 0)
1775 {
1776 /* An incomplete byte sequence remaining. */
1777 mch_memmove(conv_rest, src, size);
1778 conv_restlen = size;
1779 }
1780
1781 /* The new size is equal to how much "dst" was advanced. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001782 size = (long)(dst - ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783 }
1784 else
Bram Moolenaar13505972019-01-24 15:04:48 +01001785#endif
1786#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001787 if (fio_flags & FIO_MACROMAN)
1788 {
1789 /*
1790 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001791 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001792 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001793 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001794 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795 }
1796 else
Bram Moolenaar13505972019-01-24 15:04:48 +01001797#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001798 if (fio_flags != 0)
1799 {
1800 int u8c;
1801 char_u *dest;
1802 char_u *tail = NULL;
1803
1804 /*
1805 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1806 * "enc_utf8" not set: Convert Unicode to Latin1.
1807 * Go from end to start through the buffer, because the number
1808 * of bytes may increase.
1809 * "dest" points to after where the UTF-8 bytes go, "p" points
1810 * to after the next character to convert.
1811 */
1812 dest = ptr + real_size;
1813 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1814 {
1815 p = ptr + size;
1816 if (fio_flags == FIO_UTF8)
1817 {
1818 /* Check for a trailing incomplete UTF-8 sequence */
1819 tail = ptr + size - 1;
1820 while (tail > ptr && (*tail & 0xc0) == 0x80)
1821 --tail;
1822 if (tail + utf_byte2len(*tail) <= ptr + size)
1823 tail = NULL;
1824 else
1825 p = tail;
1826 }
1827 }
1828 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1829 {
1830 /* Check for a trailing byte */
1831 p = ptr + (size & ~1);
1832 if (size & 1)
1833 tail = p;
1834 if ((fio_flags & FIO_UTF16) && p > ptr)
1835 {
1836 /* Check for a trailing leading word */
1837 if (fio_flags & FIO_ENDIAN_L)
1838 {
1839 u8c = (*--p << 8);
1840 u8c += *--p;
1841 }
1842 else
1843 {
1844 u8c = *--p;
1845 u8c += (*--p << 8);
1846 }
1847 if (u8c >= 0xd800 && u8c <= 0xdbff)
1848 tail = p;
1849 else
1850 p += 2;
1851 }
1852 }
1853 else /* FIO_UCS4 */
1854 {
1855 /* Check for trailing 1, 2 or 3 bytes */
1856 p = ptr + (size & ~3);
1857 if (size & 3)
1858 tail = p;
1859 }
1860
1861 /* If there is a trailing incomplete sequence move it to
1862 * conv_rest[]. */
1863 if (tail != NULL)
1864 {
1865 conv_restlen = (int)((ptr + size) - tail);
1866 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1867 size -= conv_restlen;
1868 }
1869
1870
1871 while (p > ptr)
1872 {
1873 if (fio_flags & FIO_LATIN1)
1874 u8c = *--p;
1875 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1876 {
1877 if (fio_flags & FIO_ENDIAN_L)
1878 {
1879 u8c = (*--p << 8);
1880 u8c += *--p;
1881 }
1882 else
1883 {
1884 u8c = *--p;
1885 u8c += (*--p << 8);
1886 }
1887 if ((fio_flags & FIO_UTF16)
1888 && u8c >= 0xdc00 && u8c <= 0xdfff)
1889 {
1890 int u16c;
1891
1892 if (p == ptr)
1893 {
1894 /* Missing leading word. */
1895 if (can_retry)
1896 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001897 if (conv_error == 0)
1898 conv_error = readfile_linenr(linecnt,
1899 ptr, p);
1900 if (bad_char_behavior == BAD_DROP)
1901 continue;
1902 if (bad_char_behavior != BAD_KEEP)
1903 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001904 }
1905
1906 /* found second word of double-word, get the first
1907 * word and compute the resulting character */
1908 if (fio_flags & FIO_ENDIAN_L)
1909 {
1910 u16c = (*--p << 8);
1911 u16c += *--p;
1912 }
1913 else
1914 {
1915 u16c = *--p;
1916 u16c += (*--p << 8);
1917 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001918 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1919 + (u8c & 0x3ff);
1920
Bram Moolenaar071d4272004-06-13 20:20:40 +00001921 /* Check if the word is indeed a leading word. */
1922 if (u16c < 0xd800 || u16c > 0xdbff)
1923 {
1924 if (can_retry)
1925 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001926 if (conv_error == 0)
1927 conv_error = readfile_linenr(linecnt,
1928 ptr, p);
1929 if (bad_char_behavior == BAD_DROP)
1930 continue;
1931 if (bad_char_behavior != BAD_KEEP)
1932 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001933 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001934 }
1935 }
1936 else if (fio_flags & FIO_UCS4)
1937 {
1938 if (fio_flags & FIO_ENDIAN_L)
1939 {
Bram Moolenaardc1c9812017-10-27 22:15:24 +02001940 u8c = (unsigned)*--p << 24;
1941 u8c += (unsigned)*--p << 16;
1942 u8c += (unsigned)*--p << 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001943 u8c += *--p;
1944 }
1945 else /* big endian */
1946 {
1947 u8c = *--p;
Bram Moolenaardc1c9812017-10-27 22:15:24 +02001948 u8c += (unsigned)*--p << 8;
1949 u8c += (unsigned)*--p << 16;
1950 u8c += (unsigned)*--p << 24;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001951 }
1952 }
1953 else /* UTF-8 */
1954 {
1955 if (*--p < 0x80)
1956 u8c = *p;
1957 else
1958 {
1959 len = utf_head_off(ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001960 p -= len;
1961 u8c = utf_ptr2char(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001962 if (len == 0)
1963 {
1964 /* Not a valid UTF-8 character, retry with
1965 * another fenc when possible, otherwise just
1966 * report the error. */
1967 if (can_retry)
1968 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001969 if (conv_error == 0)
1970 conv_error = readfile_linenr(linecnt,
1971 ptr, p);
1972 if (bad_char_behavior == BAD_DROP)
1973 continue;
1974 if (bad_char_behavior != BAD_KEEP)
1975 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001976 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001977 }
1978 }
1979 if (enc_utf8) /* produce UTF-8 */
1980 {
1981 dest -= utf_char2len(u8c);
1982 (void)utf_char2bytes(u8c, dest);
1983 }
1984 else /* produce Latin1 */
1985 {
1986 --dest;
1987 if (u8c >= 0x100)
1988 {
1989 /* character doesn't fit in latin1, retry with
1990 * another fenc when possible, otherwise just
1991 * report the error. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001992 if (can_retry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001993 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001994 if (conv_error == 0)
1995 conv_error = readfile_linenr(linecnt, ptr, p);
1996 if (bad_char_behavior == BAD_DROP)
1997 ++dest;
1998 else if (bad_char_behavior == BAD_KEEP)
1999 *dest = u8c;
2000 else if (eap != NULL && eap->bad_char != 0)
2001 *dest = bad_char_behavior;
2002 else
2003 *dest = 0xBF;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002004 }
2005 else
2006 *dest = u8c;
2007 }
2008 }
2009
2010 /* move the linerest to before the converted characters */
2011 line_start = dest - linerest;
2012 mch_memmove(line_start, buffer, (size_t)linerest);
2013 size = (long)((ptr + real_size) - dest);
2014 ptr = dest;
2015 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002016 else if (enc_utf8 && !curbuf->b_p_bin)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002017 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002018 int incomplete_tail = FALSE;
2019
2020 /* Reading UTF-8: Check if the bytes are valid UTF-8. */
2021 for (p = ptr; ; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002022 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002023 int todo = (int)((ptr + size) - p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002024 int l;
2025
2026 if (todo <= 0)
2027 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002028 if (*p >= 0x80)
2029 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030 /* A length of 1 means it's an illegal byte. Accept
2031 * an incomplete character at the end though, the next
2032 * read() will get the next bytes, we'll check it
2033 * then. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002034 l = utf_ptr2len_len(p, todo);
Bram Moolenaarf453d352008-06-04 17:37:34 +00002035 if (l > todo && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002036 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002037 /* Avoid retrying with a different encoding when
2038 * a truncated file is more likely, or attempting
2039 * to read the rest of an incomplete sequence when
2040 * we have already done so. */
2041 if (p > ptr || filesize > 0)
2042 incomplete_tail = TRUE;
2043 /* Incomplete byte sequence, move it to conv_rest[]
2044 * and try to read the rest of it, unless we've
2045 * already done so. */
2046 if (p > ptr)
2047 {
2048 conv_restlen = todo;
2049 mch_memmove(conv_rest, p, conv_restlen);
2050 size -= conv_restlen;
2051 break;
2052 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002053 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002054 if (l == 1 || l > todo)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002055 {
2056 /* Illegal byte. If we can try another encoding
Bram Moolenaarf453d352008-06-04 17:37:34 +00002057 * do that, unless at EOF where a truncated
2058 * file is more likely than a conversion error. */
2059 if (can_retry && !incomplete_tail)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002060 break;
Bram Moolenaar13505972019-01-24 15:04:48 +01002061#ifdef USE_ICONV
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002062 /* When we did a conversion report an error. */
2063 if (iconv_fd != (iconv_t)-1 && conv_error == 0)
2064 conv_error = readfile_linenr(linecnt, ptr, p);
Bram Moolenaar13505972019-01-24 15:04:48 +01002065#endif
Bram Moolenaarf453d352008-06-04 17:37:34 +00002066 /* Remember the first linenr with an illegal byte */
2067 if (conv_error == 0 && illegal_byte == 0)
2068 illegal_byte = readfile_linenr(linecnt, ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002069
2070 /* Drop, keep or replace the bad byte. */
2071 if (bad_char_behavior == BAD_DROP)
2072 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002073 mch_memmove(p, p + 1, todo - 1);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002074 --p;
2075 --size;
2076 }
2077 else if (bad_char_behavior != BAD_KEEP)
2078 *p = bad_char_behavior;
2079 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002080 else
2081 p += l - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002082 }
2083 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002084 if (p < ptr + size && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002085 {
2086 /* Detected a UTF-8 error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002087rewind_retry:
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002088 /* Retry reading with another conversion. */
Bram Moolenaar13505972019-01-24 15:04:48 +01002089#if defined(FEAT_EVAL) && defined(USE_ICONV)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002090 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
2091 /* iconv() failed, try 'charconvert' */
2092 did_iconv = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002093 else
Bram Moolenaar13505972019-01-24 15:04:48 +01002094#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002095 /* use next item from 'fileencodings' */
2096 advance_fenc = TRUE;
2097 file_rewind = TRUE;
2098 goto retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002099 }
2100 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002101
2102 /* count the number of characters (after conversion!) */
2103 filesize += size;
2104
2105 /*
2106 * when reading the first part of a file: guess EOL type
2107 */
2108 if (fileformat == EOL_UNKNOWN)
2109 {
2110 /* First try finding a NL, for Dos and Unix */
2111 if (try_dos || try_unix)
2112 {
Bram Moolenaarc6b72172015-02-27 17:48:09 +01002113 /* Reset the carriage return counter. */
2114 if (try_mac)
2115 try_mac = 1;
2116
Bram Moolenaar071d4272004-06-13 20:20:40 +00002117 for (p = ptr; p < ptr + size; ++p)
2118 {
2119 if (*p == NL)
2120 {
2121 if (!try_unix
2122 || (try_dos && p > ptr && p[-1] == CAR))
2123 fileformat = EOL_DOS;
2124 else
2125 fileformat = EOL_UNIX;
2126 break;
2127 }
Bram Moolenaar05eb6122015-02-17 14:15:19 +01002128 else if (*p == CAR && try_mac)
2129 try_mac++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002130 }
2131
2132 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
2133 if (fileformat == EOL_UNIX && try_mac)
2134 {
2135 /* Need to reset the counters when retrying fenc. */
2136 try_mac = 1;
2137 try_unix = 1;
2138 for (; p >= ptr && *p != CAR; p--)
2139 ;
2140 if (p >= ptr)
2141 {
2142 for (p = ptr; p < ptr + size; ++p)
2143 {
2144 if (*p == NL)
2145 try_unix++;
2146 else if (*p == CAR)
2147 try_mac++;
2148 }
2149 if (try_mac > try_unix)
2150 fileformat = EOL_MAC;
2151 }
2152 }
Bram Moolenaar05eb6122015-02-17 14:15:19 +01002153 else if (fileformat == EOL_UNKNOWN && try_mac == 1)
2154 /* Looking for CR but found no end-of-line markers at
2155 * all: use the default format. */
2156 fileformat = default_fileformat();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002157 }
2158
2159 /* No NL found: may use Mac format */
2160 if (fileformat == EOL_UNKNOWN && try_mac)
2161 fileformat = EOL_MAC;
2162
2163 /* Still nothing found? Use first format in 'ffs' */
2164 if (fileformat == EOL_UNKNOWN)
2165 fileformat = default_fileformat();
2166
2167 /* if editing a new file: may set p_tx and p_ff */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002168 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002169 set_fileformat(fileformat, OPT_LOCAL);
2170 }
2171 }
2172
2173 /*
2174 * This loop is executed once for every character read.
2175 * Keep it fast!
2176 */
2177 if (fileformat == EOL_MAC)
2178 {
2179 --ptr;
2180 while (++ptr, --size >= 0)
2181 {
2182 /* catch most common case first */
2183 if ((c = *ptr) != NUL && c != CAR && c != NL)
2184 continue;
2185 if (c == NUL)
2186 *ptr = NL; /* NULs are replaced by newlines! */
2187 else if (c == NL)
2188 *ptr = CAR; /* NLs are replaced by CRs! */
2189 else
2190 {
2191 if (skip_count == 0)
2192 {
2193 *ptr = NUL; /* end of line */
2194 len = (colnr_T) (ptr - line_start + 1);
2195 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2196 {
2197 error = TRUE;
2198 break;
2199 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002200#ifdef FEAT_PERSISTENT_UNDO
2201 if (read_undo_file)
2202 sha256_update(&sha_ctx, line_start, len);
2203#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204 ++lnum;
2205 if (--read_count == 0)
2206 {
2207 error = TRUE; /* break loop */
2208 line_start = ptr; /* nothing left to write */
2209 break;
2210 }
2211 }
2212 else
2213 --skip_count;
2214 line_start = ptr + 1;
2215 }
2216 }
2217 }
2218 else
2219 {
2220 --ptr;
2221 while (++ptr, --size >= 0)
2222 {
2223 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2224 continue;
2225 if (c == NUL)
2226 *ptr = NL; /* NULs are replaced by newlines! */
2227 else
2228 {
2229 if (skip_count == 0)
2230 {
2231 *ptr = NUL; /* end of line */
2232 len = (colnr_T)(ptr - line_start + 1);
2233 if (fileformat == EOL_DOS)
2234 {
Bram Moolenaar2aa5f692017-01-24 15:46:48 +01002235 if (ptr > line_start && ptr[-1] == CAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002236 {
Bram Moolenaar2aa5f692017-01-24 15:46:48 +01002237 /* remove CR before NL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 ptr[-1] = NUL;
2239 --len;
2240 }
2241 /*
2242 * Reading in Dos format, but no CR-LF found!
2243 * When 'fileformats' includes "unix", delete all
2244 * the lines read so far and start all over again.
2245 * Otherwise give an error message later.
2246 */
2247 else if (ff_error != EOL_DOS)
2248 {
2249 if ( try_unix
2250 && !read_stdin
2251 && (read_buffer
Bram Moolenaar8767f522016-07-01 17:17:39 +02002252 || vim_lseek(fd, (off_T)0L, SEEK_SET)
2253 == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002254 {
2255 fileformat = EOL_UNIX;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002256 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002257 set_fileformat(EOL_UNIX, OPT_LOCAL);
2258 file_rewind = TRUE;
2259 keep_fileformat = TRUE;
2260 goto retry;
2261 }
2262 ff_error = EOL_DOS;
2263 }
2264 }
2265 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2266 {
2267 error = TRUE;
2268 break;
2269 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002270#ifdef FEAT_PERSISTENT_UNDO
2271 if (read_undo_file)
2272 sha256_update(&sha_ctx, line_start, len);
2273#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002274 ++lnum;
2275 if (--read_count == 0)
2276 {
2277 error = TRUE; /* break loop */
2278 line_start = ptr; /* nothing left to write */
2279 break;
2280 }
2281 }
2282 else
2283 --skip_count;
2284 line_start = ptr + 1;
2285 }
2286 }
2287 }
2288 linerest = (long)(ptr - line_start);
2289 ui_breakcheck();
2290 }
2291
2292failed:
2293 /* not an error, max. number of lines reached */
2294 if (error && read_count == 0)
2295 error = FALSE;
2296
2297 /*
2298 * If we get EOF in the middle of a line, note the fact and
2299 * complete the line ourselves.
2300 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2301 */
2302 if (!error
2303 && !got_int
2304 && linerest != 0
2305 && !(!curbuf->b_p_bin
2306 && fileformat == EOL_DOS
2307 && *line_start == Ctrl_Z
2308 && ptr == line_start + 1))
2309 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002310 /* remember for when writing */
2311 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002312 curbuf->b_p_eol = FALSE;
2313 *ptr = NUL;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002314 len = (colnr_T)(ptr - line_start + 1);
2315 if (ml_append(lnum, line_start, len, newfile) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002316 error = TRUE;
2317 else
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002318 {
2319#ifdef FEAT_PERSISTENT_UNDO
2320 if (read_undo_file)
2321 sha256_update(&sha_ctx, line_start, len);
2322#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002323 read_no_eol_lnum = ++lnum;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002324 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002325 }
2326
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002327 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002328 save_file_ff(curbuf); /* remember the current file format */
2329
2330#ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002331 if (curbuf->b_cryptstate != NULL)
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002332 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002333 crypt_free_state(curbuf->b_cryptstate);
2334 curbuf->b_cryptstate = NULL;
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002335 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002336 if (cryptkey != NULL && cryptkey != curbuf->b_p_key)
2337 crypt_free_key(cryptkey);
2338 /* Don't set cryptkey to NULL, it's used below as a flag that
2339 * encryption was used. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002340#endif
2341
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002342 /* If editing a new file: set 'fenc' for the current buffer.
2343 * Also for ":read ++edit file". */
2344 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002345 set_string_option_direct((char_u *)"fenc", -1, fenc,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002346 OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002347 if (fenc_alloced)
2348 vim_free(fenc);
Bram Moolenaar13505972019-01-24 15:04:48 +01002349#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00002350 if (iconv_fd != (iconv_t)-1)
2351 {
2352 iconv_close(iconv_fd);
2353 iconv_fd = (iconv_t)-1;
2354 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002355#endif
2356
2357 if (!read_buffer && !read_stdin)
2358 close(fd); /* errors are ignored */
Bram Moolenaarf05da212009-11-17 16:13:15 +00002359#ifdef HAVE_FD_CLOEXEC
2360 else
2361 {
2362 int fdflags = fcntl(fd, F_GETFD);
2363 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +01002364 (void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
Bram Moolenaarf05da212009-11-17 16:13:15 +00002365 }
2366#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002367 vim_free(buffer);
2368
2369#ifdef HAVE_DUP
2370 if (read_stdin)
2371 {
2372 /* Use stderr for stdin, makes shell commands work. */
2373 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +02002374 vim_ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002375 }
2376#endif
2377
Bram Moolenaar071d4272004-06-13 20:20:40 +00002378 if (tmpname != NULL)
2379 {
2380 mch_remove(tmpname); /* delete converted file */
2381 vim_free(tmpname);
2382 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002383 --no_wait_return; /* may wait for return now */
2384
2385 /*
2386 * In recovery mode everything but autocommands is skipped.
2387 */
2388 if (!recoverymode)
2389 {
2390 /* need to delete the last line, which comes from the empty buffer */
2391 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2392 {
2393#ifdef FEAT_NETBEANS_INTG
2394 netbeansFireChanges = 0;
2395#endif
2396 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2397#ifdef FEAT_NETBEANS_INTG
2398 netbeansFireChanges = 1;
2399#endif
2400 --linecnt;
2401 }
2402 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2403 if (filesize == 0)
2404 linecnt = 0;
2405 if (newfile || read_buffer)
Bram Moolenaar7263a772007-05-10 17:35:54 +00002406 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002407 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar7263a772007-05-10 17:35:54 +00002408#ifdef FEAT_DIFF
2409 /* After reading the text into the buffer the diff info needs to
2410 * be updated. */
2411 diff_invalidate(curbuf);
2412#endif
2413#ifdef FEAT_FOLDING
2414 /* All folds in the window are invalid now. Mark them for update
2415 * before triggering autocommands. */
2416 foldUpdateAll(curwin);
2417#endif
2418 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002419 else if (linecnt) /* appended at least one line */
2420 appended_lines_mark(from, linecnt);
2421
Bram Moolenaar071d4272004-06-13 20:20:40 +00002422#ifndef ALWAYS_USE_GUI
2423 /*
2424 * If we were reading from the same terminal as where messages go,
2425 * the screen will have been messed up.
2426 * Switch on raw mode now and clear the screen.
2427 */
2428 if (read_stdin)
2429 {
2430 settmode(TMODE_RAW); /* set to raw mode */
2431 starttermcap();
2432 screenclear();
2433 }
2434#endif
2435
2436 if (got_int)
2437 {
2438 if (!(flags & READ_DUMMY))
2439 {
2440 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2441 if (newfile)
2442 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2443 }
2444 msg_scroll = msg_save;
2445#ifdef FEAT_VIMINFO
2446 check_marks_read();
2447#endif
2448 return OK; /* an interrupt isn't really an error */
2449 }
2450
2451 if (!filtering && !(flags & READ_DUMMY))
2452 {
2453 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2454 c = FALSE;
2455
2456#ifdef UNIX
Bram Moolenaard569bb02018-08-11 13:57:20 +02002457 if (S_ISFIFO(perm)) /* fifo */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002458 {
2459 STRCAT(IObuff, _("[fifo]"));
2460 c = TRUE;
2461 }
Bram Moolenaard569bb02018-08-11 13:57:20 +02002462 if (S_ISSOCK(perm)) /* or socket */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463 {
2464 STRCAT(IObuff, _("[socket]"));
2465 c = TRUE;
2466 }
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002467# ifdef OPEN_CHR_FILES
2468 if (S_ISCHR(perm)) /* or character special */
2469 {
2470 STRCAT(IObuff, _("[character special]"));
2471 c = TRUE;
2472 }
2473# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002474#endif
2475 if (curbuf->b_p_ro)
2476 {
2477 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2478 c = TRUE;
2479 }
2480 if (read_no_eol_lnum)
2481 {
2482 msg_add_eol();
2483 c = TRUE;
2484 }
2485 if (ff_error == EOL_DOS)
2486 {
2487 STRCAT(IObuff, _("[CR missing]"));
2488 c = TRUE;
2489 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002490 if (split)
2491 {
2492 STRCAT(IObuff, _("[long lines split]"));
2493 c = TRUE;
2494 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002495 if (notconverted)
2496 {
2497 STRCAT(IObuff, _("[NOT converted]"));
2498 c = TRUE;
2499 }
2500 else if (converted)
2501 {
2502 STRCAT(IObuff, _("[converted]"));
2503 c = TRUE;
2504 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002505#ifdef FEAT_CRYPT
2506 if (cryptkey != NULL)
2507 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002508 crypt_append_msg(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002509 c = TRUE;
2510 }
2511#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002512 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002513 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002514 sprintf((char *)IObuff + STRLEN(IObuff),
2515 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002516 c = TRUE;
2517 }
2518 else if (illegal_byte > 0)
2519 {
2520 sprintf((char *)IObuff + STRLEN(IObuff),
2521 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2522 c = TRUE;
2523 }
Bram Moolenaar13505972019-01-24 15:04:48 +01002524 else if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002525 {
2526 STRCAT(IObuff, _("[READ ERRORS]"));
2527 c = TRUE;
2528 }
2529 if (msg_add_fileformat(fileformat))
2530 c = TRUE;
2531#ifdef FEAT_CRYPT
2532 if (cryptkey != NULL)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002533 msg_add_lines(c, (long)linecnt, filesize
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002534 - crypt_get_header_len(crypt_get_method_nr(curbuf)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002535 else
2536#endif
2537 msg_add_lines(c, (long)linecnt, filesize);
2538
Bram Moolenaard23a8232018-02-10 18:45:26 +01002539 VIM_CLEAR(keep_msg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002540 msg_scrolled_ign = TRUE;
2541#ifdef ALWAYS_USE_GUI
2542 /* Don't show the message when reading stdin, it would end up in a
2543 * message box (which might be shown when exiting!) */
2544 if (read_stdin || read_buffer)
2545 p = msg_may_trunc(FALSE, IObuff);
2546 else
2547#endif
Bram Moolenaar32526b32019-01-19 17:43:09 +01002548 p = (char_u *)msg_trunc_attr((char *)IObuff, FALSE, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002549 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002550 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002551 /* Need to repeat the message after redrawing when:
2552 * - When reading from stdin (the screen will be cleared next).
2553 * - When restart_edit is set (otherwise there will be a delay
2554 * before redrawing).
2555 * - When the screen was scrolled but there is no wait-return
2556 * prompt. */
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002557 set_keep_msg(p, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002558 msg_scrolled_ign = FALSE;
2559 }
2560
2561 /* with errors writing the file requires ":w!" */
2562 if (newfile && (error
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002563 || conv_error != 0
Bram Moolenaar13505972019-01-24 15:04:48 +01002564 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002565 curbuf->b_p_ro = TRUE;
2566
2567 u_clearline(); /* cannot use "U" command after adding lines */
2568
2569 /*
2570 * In Ex mode: cursor at last new line.
2571 * Otherwise: cursor at first new line.
2572 */
2573 if (exmode_active)
2574 curwin->w_cursor.lnum = from + linecnt;
2575 else
2576 curwin->w_cursor.lnum = from + 1;
2577 check_cursor_lnum();
2578 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2579
2580 /*
2581 * Set '[ and '] marks to the newly read lines.
2582 */
2583 curbuf->b_op_start.lnum = from + 1;
2584 curbuf->b_op_start.col = 0;
2585 curbuf->b_op_end.lnum = from + linecnt;
2586 curbuf->b_op_end.col = 0;
Bram Moolenaar03f48552006-02-28 23:52:23 +00002587
2588#ifdef WIN32
2589 /*
2590 * Work around a weird problem: When a file has two links (only
2591 * possible on NTFS) and we write through one link, then stat() it
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00002592 * through the other link, the timestamp information may be wrong.
Bram Moolenaar03f48552006-02-28 23:52:23 +00002593 * It's correct again after reading the file, thus reset the timestamp
2594 * here.
2595 */
2596 if (newfile && !read_stdin && !read_buffer
2597 && mch_stat((char *)fname, &st) >= 0)
2598 {
2599 buf_store_time(curbuf, &st, fname);
2600 curbuf->b_mtime_read = curbuf->b_mtime;
2601 }
2602#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002603 }
2604 msg_scroll = msg_save;
2605
2606#ifdef FEAT_VIMINFO
2607 /*
2608 * Get the marks before executing autocommands, so they can be used there.
2609 */
2610 check_marks_read();
2611#endif
2612
Bram Moolenaar071d4272004-06-13 20:20:40 +00002613 /*
Bram Moolenaar34d72d42015-07-17 14:18:08 +02002614 * We remember if the last line of the read didn't have
2615 * an eol even when 'binary' is off, to support turning 'fixeol' off,
2616 * or writing the read again with 'binary' on. The latter is required
2617 * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002618 */
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002619 curbuf->b_no_eol_lnum = read_no_eol_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002620
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02002621 /* When reloading a buffer put the cursor at the first line that is
2622 * different. */
2623 if (flags & READ_KEEP_UNDO)
2624 u_find_first_changed();
2625
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002626#ifdef FEAT_PERSISTENT_UNDO
2627 /*
2628 * When opening a new file locate undo info and read it.
2629 */
2630 if (read_undo_file)
2631 {
2632 char_u hash[UNDO_HASH_SIZE];
2633
2634 sha256_finish(&sha_ctx, hash);
Bram Moolenaar6ed8ed82010-05-30 20:40:11 +02002635 u_read_undo(NULL, hash, fname);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002636 }
2637#endif
2638
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02002639 if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002640 {
2641 int m = msg_scroll;
2642 int n = msg_scrolled;
2643
2644 /* Save the fileformat now, otherwise the buffer will be considered
2645 * modified if the format/encoding was automatically detected. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002646 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002647 save_file_ff(curbuf);
2648
2649 /*
2650 * The output from the autocommands should not overwrite anything and
2651 * should not be overwritten: Set msg_scroll, restore its value if no
2652 * output was done.
2653 */
2654 msg_scroll = TRUE;
2655 if (filtering)
2656 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2657 FALSE, curbuf, eap);
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02002658 else if (newfile || (read_buffer && sfname != NULL))
Bram Moolenaarc3691332016-04-20 12:49:49 +02002659 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002660 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2661 FALSE, curbuf, eap);
Bram Moolenaarc3691332016-04-20 12:49:49 +02002662 if (!au_did_filetype && *curbuf->b_p_ft != NUL)
2663 /*
2664 * EVENT_FILETYPE was not triggered but the buffer already has a
2665 * filetype. Trigger EVENT_FILETYPE using the existing filetype.
2666 */
2667 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
2668 TRUE, curbuf);
2669 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002670 else
2671 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2672 FALSE, NULL, eap);
2673 if (msg_scrolled == n)
2674 msg_scroll = m;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002675# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002676 if (aborting()) /* autocmds may abort script processing */
2677 return FAIL;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002678# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002679 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002680
2681 if (recoverymode && error)
2682 return FAIL;
2683 return OK;
2684}
2685
Bram Moolenaarf04507d2016-08-20 15:05:39 +02002686#if defined(OPEN_CHR_FILES) || defined(PROTO)
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002687/*
2688 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2689 * which is the name of files used for process substitution output by
2690 * some shells on some operating systems, e.g., bash on SunOS.
2691 * Do not accept "/dev/fd/[012]", opening these may hang Vim.
2692 */
Bram Moolenaarf04507d2016-08-20 15:05:39 +02002693 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002694is_dev_fd_file(char_u *fname)
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002695{
2696 return (STRNCMP(fname, "/dev/fd/", 8) == 0
2697 && VIM_ISDIGIT(fname[8])
2698 && *skipdigits(fname + 9) == NUL
2699 && (fname[9] != NUL
2700 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
2701}
2702#endif
2703
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002704/*
2705 * From the current line count and characters read after that, estimate the
2706 * line number where we are now.
2707 * Used for error messages that include a line number.
2708 */
2709 static linenr_T
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002710readfile_linenr(
2711 linenr_T linecnt, /* line count before reading more bytes */
2712 char_u *p, /* start of more bytes read */
2713 char_u *endp) /* end of more bytes read */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002714{
2715 char_u *s;
2716 linenr_T lnum;
2717
2718 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2719 for (s = p; s < endp; ++s)
2720 if (*s == '\n')
2721 ++lnum;
2722 return lnum;
2723}
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002724
Bram Moolenaar071d4272004-06-13 20:20:40 +00002725/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002726 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2727 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002728 * Returns OK or FAIL.
2729 */
2730 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002731prep_exarg(exarg_T *eap, buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002732{
Bram Moolenaar13505972019-01-24 15:04:48 +01002733 eap->cmd = alloc(15 + (unsigned)STRLEN(buf->b_p_fenc));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002734 if (eap->cmd == NULL)
2735 return FAIL;
2736
Bram Moolenaar333b80a2018-04-04 22:57:29 +02002737 sprintf((char *)eap->cmd, "e ++enc=%s", buf->b_p_fenc);
2738 eap->force_enc = 8;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002739 eap->bad_char = buf->b_bad_char;
Bram Moolenaar333b80a2018-04-04 22:57:29 +02002740 eap->force_ff = *buf->b_p_ff;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002741
2742 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002743 eap->read_edit = FALSE;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002744 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002745 return OK;
2746}
2747
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002748/*
2749 * Set default or forced 'fileformat' and 'binary'.
2750 */
2751 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002752set_file_options(int set_options, exarg_T *eap)
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002753{
2754 /* set default 'fileformat' */
2755 if (set_options)
2756 {
2757 if (eap != NULL && eap->force_ff != 0)
2758 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
2759 else if (*p_ffs != NUL)
2760 set_fileformat(default_fileformat(), OPT_LOCAL);
2761 }
2762
2763 /* set or reset 'binary' */
2764 if (eap != NULL && eap->force_bin != 0)
2765 {
2766 int oldval = curbuf->b_p_bin;
2767
2768 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
2769 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
2770 }
2771}
2772
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002773/*
2774 * Set forced 'fileencoding'.
2775 */
2776 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002777set_forced_fenc(exarg_T *eap)
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002778{
2779 if (eap->force_enc != 0)
2780 {
2781 char_u *fenc = enc_canonize(eap->cmd + eap->force_enc);
2782
2783 if (fenc != NULL)
2784 set_string_option_direct((char_u *)"fenc", -1,
2785 fenc, OPT_FREE|OPT_LOCAL, 0);
2786 vim_free(fenc);
2787 }
2788}
2789
Bram Moolenaar071d4272004-06-13 20:20:40 +00002790/*
2791 * Find next fileencoding to use from 'fileencodings'.
2792 * "pp" points to fenc_next. It's advanced to the next item.
2793 * When there are no more items, an empty string is returned and *pp is set to
2794 * NULL.
2795 * When *pp is not set to NULL, the result is in allocated memory.
2796 */
2797 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002798next_fenc(char_u **pp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002799{
2800 char_u *p;
2801 char_u *r;
2802
2803 if (**pp == NUL)
2804 {
2805 *pp = NULL;
2806 return (char_u *)"";
2807 }
2808 p = vim_strchr(*pp, ',');
2809 if (p == NULL)
2810 {
2811 r = enc_canonize(*pp);
2812 *pp += STRLEN(*pp);
2813 }
2814 else
2815 {
2816 r = vim_strnsave(*pp, (int)(p - *pp));
2817 *pp = p + 1;
2818 if (r != NULL)
2819 {
2820 p = enc_canonize(r);
2821 vim_free(r);
2822 r = p;
2823 }
2824 }
2825 if (r == NULL) /* out of memory */
2826 {
2827 r = (char_u *)"";
2828 *pp = NULL;
2829 }
2830 return r;
2831}
2832
Bram Moolenaar13505972019-01-24 15:04:48 +01002833#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002834/*
2835 * Convert a file with the 'charconvert' expression.
2836 * This closes the file which is to be read, converts it and opens the
2837 * resulting file for reading.
2838 * Returns name of the resulting converted file (the caller should delete it
2839 * after reading it).
2840 * Returns NULL if the conversion failed ("*fdp" is not set) .
2841 */
2842 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002843readfile_charconvert(
2844 char_u *fname, /* name of input file */
2845 char_u *fenc, /* converted from */
2846 int *fdp) /* in/out: file descriptor of file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002847{
2848 char_u *tmpname;
Bram Moolenaar32526b32019-01-19 17:43:09 +01002849 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002850
Bram Moolenaare5c421c2015-03-31 13:33:08 +02002851 tmpname = vim_tempname('r', FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002852 if (tmpname == NULL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01002853 errmsg = _("Can't find temp file for conversion");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854 else
2855 {
2856 close(*fdp); /* close the input file, ignore errors */
2857 *fdp = -1;
2858 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2859 fname, tmpname) == FAIL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01002860 errmsg = _("Conversion with 'charconvert' failed");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2862 O_RDONLY | O_EXTRA, 0)) < 0)
Bram Moolenaar32526b32019-01-19 17:43:09 +01002863 errmsg = _("can't read output of 'charconvert'");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002864 }
2865
2866 if (errmsg != NULL)
2867 {
2868 /* Don't use emsg(), it breaks mappings, the retry with
2869 * another type of conversion might still work. */
Bram Moolenaar32526b32019-01-19 17:43:09 +01002870 msg(errmsg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871 if (tmpname != NULL)
2872 {
2873 mch_remove(tmpname); /* delete converted file */
Bram Moolenaard23a8232018-02-10 18:45:26 +01002874 VIM_CLEAR(tmpname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 }
2876 }
2877
2878 /* If the input file is closed, open it (caller should check for error). */
2879 if (*fdp < 0)
2880 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2881
2882 return tmpname;
2883}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002884#endif
2885
Bram Moolenaar13505972019-01-24 15:04:48 +01002886
Bram Moolenaar071d4272004-06-13 20:20:40 +00002887#ifdef FEAT_VIMINFO
2888/*
2889 * Read marks for the current buffer from the viminfo file, when we support
2890 * buffer marks and the buffer has a name.
2891 */
2892 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002893check_marks_read(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002894{
2895 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2896 && curbuf->b_ffname != NULL)
Bram Moolenaard812df62008-11-09 12:46:09 +00002897 read_viminfo(NULL, VIF_WANT_MARKS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002898
2899 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2900 * the ' parameter after opening a buffer. */
2901 curbuf->b_marks_read = TRUE;
2902}
2903#endif
2904
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02002905#if defined(FEAT_CRYPT) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002906/*
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002907 * Check for magic number used for encryption. Applies to the current buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2909 * *filesizep are updated.
2910 * Return the (new) encryption key, NULL for no encryption.
2911 */
2912 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002913check_for_cryptkey(
2914 char_u *cryptkey, /* previous encryption key or NULL */
2915 char_u *ptr, /* pointer to read bytes */
2916 long *sizep, /* length of read bytes */
Bram Moolenaar8767f522016-07-01 17:17:39 +02002917 off_T *filesizep, /* nr of bytes used from file */
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002918 int newfile, /* editing a new buffer */
2919 char_u *fname, /* file name to display */
2920 int *did_ask) /* flag: whether already asked for key */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921{
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002922 int method = crypt_method_nr_from_magic((char *)ptr, *sizep);
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002923 int b_p_ro = curbuf->b_p_ro;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002924
2925 if (method >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926 {
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002927 /* Mark the buffer as read-only until the decryption has taken place.
2928 * Avoids accidentally overwriting the file with garbage. */
2929 curbuf->b_p_ro = TRUE;
2930
Bram Moolenaar2be79502014-08-13 21:58:28 +02002931 /* Set the cryptmethod local to the buffer. */
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002932 crypt_set_cm_option(curbuf, method);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002933 if (cryptkey == NULL && !*did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002934 {
2935 if (*curbuf->b_p_key)
2936 cryptkey = curbuf->b_p_key;
2937 else
2938 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002939 /* When newfile is TRUE, store the typed key in the 'key'
2940 * option and don't free it. bf needs hash of the key saved.
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002941 * Don't ask for the key again when first time Enter was hit.
2942 * Happens when retrying to detect encoding. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002943 smsg(_(need_key_msg), fname);
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002944 msg_scroll = TRUE;
Bram Moolenaar3a0c9082014-11-12 15:15:42 +01002945 crypt_check_method(method);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002946 cryptkey = crypt_get_key(newfile, FALSE);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002947 *did_ask = TRUE;
2948
Bram Moolenaar071d4272004-06-13 20:20:40 +00002949 /* check if empty key entered */
2950 if (cryptkey != NULL && *cryptkey == NUL)
2951 {
2952 if (cryptkey != curbuf->b_p_key)
2953 vim_free(cryptkey);
2954 cryptkey = NULL;
2955 }
2956 }
2957 }
2958
2959 if (cryptkey != NULL)
2960 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002961 int header_len;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002962
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002963 curbuf->b_cryptstate = crypt_create_from_header(
2964 method, cryptkey, ptr);
2965 crypt_set_cm_option(curbuf, method);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002966
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002967 /* Remove cryptmethod specific header from the text. */
2968 header_len = crypt_get_header_len(method);
Bram Moolenaar680e0152016-09-25 20:54:11 +02002969 if (*sizep <= header_len)
2970 /* invalid header, buffer can't be encrypted */
2971 return NULL;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002972 *filesizep += header_len;
2973 *sizep -= header_len;
2974 mch_memmove(ptr, ptr + header_len, (size_t)*sizep);
2975
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002976 /* Restore the read-only flag. */
2977 curbuf->b_p_ro = b_p_ro;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 }
2979 }
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002980 /* When starting to edit a new file which does not have encryption, clear
2981 * the 'key' option, except when starting up (called with -x argument) */
Bram Moolenaarfa0ff9a2010-07-25 16:05:19 +02002982 else if (newfile && *curbuf->b_p_key != NUL && !starting)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2984
2985 return cryptkey;
2986}
Bram Moolenaar80794b12010-06-13 05:20:42 +02002987#endif /* FEAT_CRYPT */
2988
Bram Moolenaar071d4272004-06-13 20:20:40 +00002989#ifdef UNIX
2990 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002991set_file_time(
2992 char_u *fname,
2993 time_t atime, /* access time */
2994 time_t mtime) /* modification time */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002995{
2996# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
2997 struct utimbuf buf;
2998
2999 buf.actime = atime;
3000 buf.modtime = mtime;
3001 (void)utime((char *)fname, &buf);
3002# else
3003# if defined(HAVE_UTIMES)
3004 struct timeval tvp[2];
3005
3006 tvp[0].tv_sec = atime;
3007 tvp[0].tv_usec = 0;
3008 tvp[1].tv_sec = mtime;
3009 tvp[1].tv_usec = 0;
3010# ifdef NeXT
3011 (void)utimes((char *)fname, tvp);
3012# else
3013 (void)utimes((char *)fname, (const struct timeval *)&tvp);
3014# endif
3015# endif
3016# endif
3017}
3018#endif /* UNIX */
3019
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003020#if defined(VMS) && !defined(MIN)
3021/* Older DECC compiler for VAX doesn't define MIN() */
3022# define MIN(a, b) ((a) < (b) ? (a) : (b))
3023#endif
3024
Bram Moolenaar071d4272004-06-13 20:20:40 +00003025/*
Bram Moolenaar5386a122007-06-28 20:02:32 +00003026 * Return TRUE if a file appears to be read-only from the file permissions.
3027 */
3028 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003029check_file_readonly(
3030 char_u *fname, /* full path to file */
3031 int perm) /* known permissions on file */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003032{
3033#ifndef USE_MCH_ACCESS
3034 int fd = 0;
3035#endif
3036
3037 return (
3038#ifdef USE_MCH_ACCESS
3039# ifdef UNIX
3040 (perm & 0222) == 0 ||
3041# endif
3042 mch_access((char *)fname, W_OK)
3043#else
3044 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
3045 ? TRUE : (close(fd), FALSE)
3046#endif
3047 );
3048}
3049
3050
3051/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00003052 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00003053 *
3054 * We do our own buffering here because fwrite() is so slow.
3055 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00003056 * If "forceit" is true, we don't care for errors when attempting backups.
3057 * In case of an error everything possible is done to restore the original
Bram Moolenaare37d50a2008-08-06 17:06:04 +00003058 * file. But when "forceit" is TRUE, we risk losing it.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003059 *
3060 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
3061 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003062 *
3063 * This function must NOT use NameBuff (because it's called by autowrite()).
3064 *
3065 * return FAIL for failure, OK otherwise
3066 */
3067 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003068buf_write(
3069 buf_T *buf,
3070 char_u *fname,
3071 char_u *sfname,
3072 linenr_T start,
3073 linenr_T end,
3074 exarg_T *eap, /* for forced 'ff' and 'fenc', can be
Bram Moolenaar071d4272004-06-13 20:20:40 +00003075 NULL! */
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003076 int append, /* append to the file */
3077 int forceit,
3078 int reset_changed,
3079 int filtering)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003080{
3081 int fd;
3082 char_u *backup = NULL;
3083 int backup_copy = FALSE; /* copy the original file? */
3084 int dobackup;
3085 char_u *ffname;
3086 char_u *wfname = NULL; /* name of file to write to */
3087 char_u *s;
3088 char_u *ptr;
3089 char_u c;
3090 int len;
3091 linenr_T lnum;
3092 long nchars;
3093 char_u *errmsg = NULL;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003094 int errmsg_allocated = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003095 char_u *errnum = NULL;
3096 char_u *buffer;
3097 char_u smallbuf[SMBUFSIZE];
3098 char_u *backup_ext;
3099 int bufsize;
3100 long perm; /* file permissions */
3101 int retval = OK;
3102 int newfile = FALSE; /* TRUE if file doesn't exist yet */
3103 int msg_save = msg_scroll;
3104 int overwriting; /* TRUE if writing over original */
3105 int no_eol = FALSE; /* no end-of-line written */
3106 int device = FALSE; /* writing to a device */
Bram Moolenaar8767f522016-07-01 17:17:39 +02003107 stat_T st_old;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003108 int prev_got_int = got_int;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02003109 int checking_conversion;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110 int file_readonly = FALSE; /* overwritten file is read-only */
3111 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003112#if defined(UNIX) /*XXX fix me sometime? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003113 int made_writable = FALSE; /* 'w' bit has been set */
3114#endif
3115 /* writing everything */
3116 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003117 linenr_T old_line_count = buf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003118 int attr;
3119 int fileformat;
3120 int write_bin;
3121 struct bw_info write_info; /* info for buf_write_bytes() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003122 int converted = FALSE;
3123 int notconverted = FALSE;
3124 char_u *fenc; /* effective 'fileencoding' */
3125 char_u *fenc_tofree = NULL; /* allocated "fenc" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003126#ifdef HAS_BW_FLAGS
3127 int wb_flags = 0;
3128#endif
3129#ifdef HAVE_ACL
3130 vim_acl_T acl = NULL; /* ACL copied from original file to
3131 backup or new file */
3132#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02003133#ifdef FEAT_PERSISTENT_UNDO
3134 int write_undo_file = FALSE;
3135 context_sha256_T sha_ctx;
3136#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003137 unsigned int bkc = get_bkc_value(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003138
3139 if (fname == NULL || *fname == NUL) /* safety check */
3140 return FAIL;
Bram Moolenaar70d60e92009-12-31 13:53:33 +00003141 if (buf->b_ml.ml_mfp == NULL)
3142 {
3143 /* This can happen during startup when there is a stray "w" in the
3144 * vimrc file. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003145 emsg(_(e_emptybuf));
Bram Moolenaar70d60e92009-12-31 13:53:33 +00003146 return FAIL;
3147 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003148
3149 /*
3150 * Disallow writing from .exrc and .vimrc in current directory for
3151 * security reasons.
3152 */
3153 if (check_secure())
3154 return FAIL;
3155
3156 /* Avoid a crash for a long name. */
3157 if (STRLEN(fname) >= MAXPATHL)
3158 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003159 emsg(_(e_longname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003160 return FAIL;
3161 }
3162
Bram Moolenaar071d4272004-06-13 20:20:40 +00003163 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
3164 write_info.bw_conv_buf = NULL;
3165 write_info.bw_conv_error = FALSE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003166 write_info.bw_conv_error_lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003167 write_info.bw_restlen = 0;
Bram Moolenaar13505972019-01-24 15:04:48 +01003168#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00003169 write_info.bw_iconv_fd = (iconv_t)-1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003171#ifdef FEAT_CRYPT
3172 write_info.bw_buffer = buf;
3173#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003174
Bram Moolenaardf177f62005-02-22 08:39:57 +00003175 /* After writing a file changedtick changes but we don't want to display
3176 * the line. */
3177 ex_no_reprint = TRUE;
3178
Bram Moolenaar071d4272004-06-13 20:20:40 +00003179 /*
3180 * If there is no file name yet, use the one for the written file.
3181 * BF_NOTEDITED is set to reflect this (in case the write fails).
3182 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003183 * Don't do this when appending.
3184 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003185 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003186 if (buf->b_ffname == NULL
3187 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00003188 && whole
3189 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00003190#ifdef FEAT_QUICKFIX
3191 && !bt_nofile(buf)
3192#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00003194 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003195 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
3196 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003197 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003198 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003199 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003200 }
3201
3202 if (sfname == NULL)
3203 sfname = fname;
3204 /*
3205 * For Unix: Use the short file name whenever possible.
3206 * Avoids problems with networks and when directory names are changed.
3207 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
3208 * another directory, which we don't detect
3209 */
3210 ffname = fname; /* remember full fname */
3211#ifdef UNIX
3212 fname = sfname;
3213#endif
3214
3215 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
3216 overwriting = TRUE;
3217 else
3218 overwriting = FALSE;
3219
3220 if (exiting)
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003221 settmode(TMODE_COOK); /* when exiting allow typeahead now */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222
3223 ++no_wait_return; /* don't wait for return yet */
3224
3225 /*
3226 * Set '[ and '] marks to the lines to be written.
3227 */
3228 buf->b_op_start.lnum = start;
3229 buf->b_op_start.col = 0;
3230 buf->b_op_end.lnum = end;
3231 buf->b_op_end.col = 0;
3232
Bram Moolenaar071d4272004-06-13 20:20:40 +00003233 {
3234 aco_save_T aco;
3235 int buf_ffname = FALSE;
3236 int buf_sfname = FALSE;
3237 int buf_fname_f = FALSE;
3238 int buf_fname_s = FALSE;
3239 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003240 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003241 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003242 bufref_T bufref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003243
3244 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003245 * Apply PRE autocommands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003246 * Set curbuf to the buffer to be written.
3247 * Careful: The autocommands may call buf_write() recursively!
3248 */
3249 if (ffname == buf->b_ffname)
3250 buf_ffname = TRUE;
3251 if (sfname == buf->b_sfname)
3252 buf_sfname = TRUE;
3253 if (fname == buf->b_ffname)
3254 buf_fname_f = TRUE;
3255 if (fname == buf->b_sfname)
3256 buf_fname_s = TRUE;
3257
3258 /* set curwin/curbuf to buf and save a few things */
3259 aucmd_prepbuf(&aco, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003260 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003261
3262 if (append)
3263 {
3264 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
3265 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003266 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003267#ifdef FEAT_QUICKFIX
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003268 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003269 nofile_err = TRUE;
3270 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003271#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003272 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003273 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003274 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003275 }
3276 else if (filtering)
3277 {
3278 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
3279 NULL, sfname, FALSE, curbuf, eap);
3280 }
3281 else if (reset_changed && whole)
3282 {
Bram Moolenaar39fc42e2011-09-02 11:56:20 +02003283 int was_changed = curbufIsChanged();
3284
3285 did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
3286 sfname, sfname, FALSE, curbuf, eap);
3287 if (did_cmd)
3288 {
3289 if (was_changed && !curbufIsChanged())
3290 {
3291 /* Written everything correctly and BufWriteCmd has reset
3292 * 'modified': Correct the undo information so that an
3293 * undo now sets 'modified'. */
3294 u_unchanged(curbuf);
3295 u_update_save_nr(curbuf);
3296 }
3297 }
3298 else
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003299 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003300#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003301 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003302 nofile_err = TRUE;
3303 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003304#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003305 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003306 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003307 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308 }
3309 else
3310 {
3311 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
3312 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003313 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003314#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003315 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003316 nofile_err = TRUE;
3317 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003318#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003319 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003320 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003321 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322 }
3323
3324 /* restore curwin/curbuf and a few other things */
3325 aucmd_restbuf(&aco);
3326
3327 /*
3328 * In three situations we return here and don't write the file:
3329 * 1. the autocommands deleted or unloaded the buffer.
3330 * 2. The autocommands abort script processing.
3331 * 3. If one of the "Cmd" autocommands was executed.
3332 */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003333 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003334 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003335 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar1e015462005-09-25 22:16:38 +00003336 || did_cmd || nofile_err
3337#ifdef FEAT_EVAL
3338 || aborting()
3339#endif
3340 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003341 {
3342 --no_wait_return;
3343 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003344 if (nofile_err)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003345 emsg(_("E676: No matching autocommands for acwrite buffer"));
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003346
Bram Moolenaar1e015462005-09-25 22:16:38 +00003347 if (nofile_err
3348#ifdef FEAT_EVAL
3349 || aborting()
3350#endif
3351 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003352 /* An aborting error, interrupt or exception in the
3353 * autocommands. */
3354 return FAIL;
3355 if (did_cmd)
3356 {
3357 if (buf == NULL)
3358 /* The buffer was deleted. We assume it was written
3359 * (can't retry anyway). */
3360 return OK;
3361 if (overwriting)
3362 {
3363 /* Assume the buffer was written, update the timestamp. */
3364 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00003365 if (append)
3366 buf->b_flags &= ~BF_NEW;
3367 else
3368 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003369 }
Bram Moolenaar292ad192005-12-11 21:29:51 +00003370 if (reset_changed && buf->b_changed && !append
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003371 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372 /* Buffer still changed, the autocommands didn't work
3373 * properly. */
3374 return FAIL;
3375 return OK;
3376 }
3377#ifdef FEAT_EVAL
3378 if (!aborting())
3379#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003380 emsg(_("E203: Autocommands deleted or unloaded buffer to be written"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003381 return FAIL;
3382 }
3383
3384 /*
3385 * The autocommands may have changed the number of lines in the file.
3386 * When writing the whole file, adjust the end.
3387 * When writing part of the file, assume that the autocommands only
3388 * changed the number of lines that are to be written (tricky!).
3389 */
3390 if (buf->b_ml.ml_line_count != old_line_count)
3391 {
3392 if (whole) /* write all */
3393 end = buf->b_ml.ml_line_count;
3394 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
3395 end += buf->b_ml.ml_line_count - old_line_count;
3396 else /* less lines */
3397 {
3398 end -= old_line_count - buf->b_ml.ml_line_count;
3399 if (end < start)
3400 {
3401 --no_wait_return;
3402 msg_scroll = msg_save;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003403 emsg(_("E204: Autocommand changed number of lines in unexpected way"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003404 return FAIL;
3405 }
3406 }
3407 }
3408
3409 /*
3410 * The autocommands may have changed the name of the buffer, which may
3411 * be kept in fname, ffname and sfname.
3412 */
3413 if (buf_ffname)
3414 ffname = buf->b_ffname;
3415 if (buf_sfname)
3416 sfname = buf->b_sfname;
3417 if (buf_fname_f)
3418 fname = buf->b_ffname;
3419 if (buf_fname_s)
3420 fname = buf->b_sfname;
3421 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003422
3423#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003424 if (netbeans_active() && isNetbeansBuffer(buf))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003425 {
3426 if (whole)
3427 {
3428 /*
3429 * b_changed can be 0 after an undo, but we still need to write
3430 * the buffer to NetBeans.
3431 */
3432 if (buf->b_changed || isNetbeansModified(buf))
3433 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00003434 --no_wait_return; /* may wait for return now */
3435 msg_scroll = msg_save;
3436 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003437 return retval;
3438 }
3439 else
3440 {
3441 errnum = (char_u *)"E656: ";
Bram Moolenaared0e7452008-06-27 19:17:34 +00003442 errmsg = (char_u *)_("NetBeans disallows writes of unmodified buffers");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003443 buffer = NULL;
3444 goto fail;
3445 }
3446 }
3447 else
3448 {
3449 errnum = (char_u *)"E657: ";
3450 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
3451 buffer = NULL;
3452 goto fail;
3453 }
3454 }
3455#endif
3456
3457 if (shortmess(SHM_OVER) && !exiting)
3458 msg_scroll = FALSE; /* overwrite previous file message */
3459 else
3460 msg_scroll = TRUE; /* don't overwrite previous file message */
3461 if (!filtering)
3462 filemess(buf,
3463#ifndef UNIX
3464 sfname,
3465#else
3466 fname,
3467#endif
3468 (char_u *)"", 0); /* show that we are busy */
3469 msg_scroll = FALSE; /* always overwrite the file message now */
3470
3471 buffer = alloc(BUFSIZE);
3472 if (buffer == NULL) /* can't allocate big buffer, use small
3473 * one (to be able to write when out of
3474 * memory) */
3475 {
3476 buffer = smallbuf;
3477 bufsize = SMBUFSIZE;
3478 }
3479 else
3480 bufsize = BUFSIZE;
3481
3482 /*
3483 * Get information about original file (if there is one).
3484 */
Bram Moolenaar53076832015-12-31 19:53:21 +01003485#if defined(UNIX)
Bram Moolenaar6f192452007-11-08 19:49:02 +00003486 st_old.st_dev = 0;
3487 st_old.st_ino = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003488 perm = -1;
3489 if (mch_stat((char *)fname, &st_old) < 0)
3490 newfile = TRUE;
3491 else
3492 {
3493 perm = st_old.st_mode;
3494 if (!S_ISREG(st_old.st_mode)) /* not a file */
3495 {
3496 if (S_ISDIR(st_old.st_mode))
3497 {
3498 errnum = (char_u *)"E502: ";
3499 errmsg = (char_u *)_("is a directory");
3500 goto fail;
3501 }
3502 if (mch_nodetype(fname) != NODE_WRITABLE)
3503 {
3504 errnum = (char_u *)"E503: ";
3505 errmsg = (char_u *)_("is not a file or writable device");
3506 goto fail;
3507 }
3508 /* It's a device of some kind (or a fifo) which we can write to
3509 * but for which we can't make a backup. */
3510 device = TRUE;
3511 newfile = TRUE;
3512 perm = -1;
3513 }
3514 }
3515#else /* !UNIX */
3516 /*
3517 * Check for a writable device name.
3518 */
3519 c = mch_nodetype(fname);
3520 if (c == NODE_OTHER)
3521 {
3522 errnum = (char_u *)"E503: ";
3523 errmsg = (char_u *)_("is not a file or writable device");
3524 goto fail;
3525 }
3526 if (c == NODE_WRITABLE)
3527 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003528# if defined(MSWIN)
Bram Moolenaar043545e2006-10-10 16:44:07 +00003529 /* MS-Windows allows opening a device, but we will probably get stuck
3530 * trying to write to it. */
3531 if (!p_odev)
3532 {
3533 errnum = (char_u *)"E796: ";
3534 errmsg = (char_u *)_("writing to device disabled with 'opendevice' option");
3535 goto fail;
3536 }
3537# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003538 device = TRUE;
3539 newfile = TRUE;
3540 perm = -1;
3541 }
3542 else
3543 {
3544 perm = mch_getperm(fname);
3545 if (perm < 0)
3546 newfile = TRUE;
3547 else if (mch_isdir(fname))
3548 {
3549 errnum = (char_u *)"E502: ";
3550 errmsg = (char_u *)_("is a directory");
3551 goto fail;
3552 }
3553 if (overwriting)
3554 (void)mch_stat((char *)fname, &st_old);
3555 }
3556#endif /* !UNIX */
3557
3558 if (!device && !newfile)
3559 {
3560 /*
3561 * Check if the file is really writable (when renaming the file to
3562 * make a backup we won't discover it later).
3563 */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003564 file_readonly = check_file_readonly(fname, (int)perm);
3565
Bram Moolenaar071d4272004-06-13 20:20:40 +00003566 if (!forceit && file_readonly)
3567 {
3568 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3569 {
3570 errnum = (char_u *)"E504: ";
3571 errmsg = (char_u *)_(err_readonly);
3572 }
3573 else
3574 {
3575 errnum = (char_u *)"E505: ";
3576 errmsg = (char_u *)_("is read-only (add ! to override)");
3577 }
3578 goto fail;
3579 }
3580
3581 /*
3582 * Check if the timestamp hasn't changed since reading the file.
3583 */
3584 if (overwriting)
3585 {
3586 retval = check_mtime(buf, &st_old);
3587 if (retval == FAIL)
3588 goto fail;
3589 }
3590 }
3591
3592#ifdef HAVE_ACL
3593 /*
3594 * For systems that support ACL: get the ACL from the original file.
3595 */
3596 if (!newfile)
3597 acl = mch_get_acl(fname);
3598#endif
3599
3600 /*
3601 * If 'backupskip' is not empty, don't make a backup for some files.
3602 */
3603 dobackup = (p_wb || p_bk || *p_pm != NUL);
3604#ifdef FEAT_WILDIGN
3605 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3606 dobackup = FALSE;
3607#endif
3608
3609 /*
3610 * Save the value of got_int and reset it. We don't want a previous
3611 * interruption cancel writing, only hitting CTRL-C while writing should
3612 * abort it.
3613 */
3614 prev_got_int = got_int;
3615 got_int = FALSE;
3616
3617 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3618 buf->b_saving = TRUE;
3619
3620 /*
3621 * If we are not appending or filtering, the file exists, and the
3622 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3623 * When 'patchmode' is set also make a backup when appending.
3624 *
3625 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3626 * off. This helps when editing large files on almost-full disks.
3627 */
3628 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3629 {
3630#if defined(UNIX) || defined(WIN32)
Bram Moolenaar8767f522016-07-01 17:17:39 +02003631 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632#endif
3633
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003634 if ((bkc & BKC_YES) || append) /* "yes" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003635 backup_copy = TRUE;
3636#if defined(UNIX) || defined(WIN32)
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003637 else if ((bkc & BKC_AUTO)) /* "auto" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003638 {
3639 int i;
3640
3641# ifdef UNIX
3642 /*
3643 * Don't rename the file when:
3644 * - it's a hard link
3645 * - it's a symbolic link
3646 * - we don't have write permission in the directory
3647 * - we can't set the owner/group of the new file
3648 */
3649 if (st_old.st_nlink > 1
3650 || mch_lstat((char *)fname, &st) < 0
3651 || st.st_dev != st_old.st_dev
Bram Moolenaara5792f52005-11-23 21:25:05 +00003652 || st.st_ino != st_old.st_ino
3653# ifndef HAVE_FCHOWN
3654 || st.st_uid != st_old.st_uid
3655 || st.st_gid != st_old.st_gid
3656# endif
3657 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003658 backup_copy = TRUE;
3659 else
Bram Moolenaar03f48552006-02-28 23:52:23 +00003660# else
3661# ifdef WIN32
3662 /* On NTFS file systems hard links are possible. */
3663 if (mch_is_linked(fname))
3664 backup_copy = TRUE;
3665 else
3666# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003667# endif
3668 {
3669 /*
3670 * Check if we can create a file and set the owner/group to
3671 * the ones from the original file.
3672 * First find a file name that doesn't exist yet (use some
3673 * arbitrary numbers).
3674 */
3675 STRCPY(IObuff, fname);
3676 for (i = 4913; ; i += 123)
3677 {
3678 sprintf((char *)gettail(IObuff), "%d", i);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003679 if (mch_lstat((char *)IObuff, &st) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003680 break;
3681 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00003682 fd = mch_open((char *)IObuff,
3683 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003684 if (fd < 0) /* can't write in directory */
3685 backup_copy = TRUE;
3686 else
3687 {
3688# ifdef UNIX
Bram Moolenaara5792f52005-11-23 21:25:05 +00003689# ifdef HAVE_FCHOWN
Bram Moolenaar42335f52018-09-13 15:33:43 +02003690 vim_ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003691# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003692 if (mch_stat((char *)IObuff, &st) < 0
3693 || st.st_uid != st_old.st_uid
3694 || st.st_gid != st_old.st_gid
Bram Moolenaar78a15312009-05-15 19:33:18 +00003695 || (long)st.st_mode != perm)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003696 backup_copy = TRUE;
3697# endif
Bram Moolenaar98358622005-11-28 22:58:23 +00003698 /* Close the file before removing it, on MS-Windows we
3699 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003700 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003701 mch_remove(IObuff);
Bram Moolenaar3479c5d2010-08-08 18:46:06 +02003702# ifdef MSWIN
3703 /* MS-Windows may trigger a virus scanner to open the
3704 * file, we can't delete it then. Keep trying for half a
3705 * second. */
3706 {
3707 int try;
3708
3709 for (try = 0; try < 10; ++try)
3710 {
3711 if (mch_lstat((char *)IObuff, &st) < 0)
3712 break;
3713 ui_delay(50L, TRUE); /* wait 50 msec */
3714 mch_remove(IObuff);
3715 }
3716 }
3717# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003718 }
3719 }
3720 }
3721
Bram Moolenaar071d4272004-06-13 20:20:40 +00003722 /*
3723 * Break symlinks and/or hardlinks if we've been asked to.
3724 */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003725 if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 {
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003727# ifdef UNIX
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 int lstat_res;
3729
3730 lstat_res = mch_lstat((char *)fname, &st);
3731
3732 /* Symlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003733 if ((bkc & BKC_BREAKSYMLINK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003734 && lstat_res == 0
3735 && st.st_ino != st_old.st_ino)
3736 backup_copy = FALSE;
3737
3738 /* Hardlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003739 if ((bkc & BKC_BREAKHARDLINK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740 && st_old.st_nlink > 1
3741 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3742 backup_copy = FALSE;
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003743# else
3744# if defined(WIN32)
3745 /* Symlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003746 if ((bkc & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname))
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003747 backup_copy = FALSE;
3748
3749 /* Hardlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003750 if ((bkc & BKC_BREAKHARDLINK) && mch_is_hard_link(fname))
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003751 backup_copy = FALSE;
3752# endif
3753# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003754 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003755
3756#endif
3757
3758 /* make sure we have a valid backup extension to use */
3759 if (*p_bex == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003760 backup_ext = (char_u *)".bak";
Bram Moolenaar071d4272004-06-13 20:20:40 +00003761 else
3762 backup_ext = p_bex;
3763
3764 if (backup_copy
3765 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3766 {
3767 int bfd;
3768 char_u *copybuf, *wp;
3769 int some_error = FALSE;
Bram Moolenaar8767f522016-07-01 17:17:39 +02003770 stat_T st_new;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 char_u *dirp;
3772 char_u *rootname;
Bram Moolenaarb782ba42018-08-07 21:39:28 +02003773#if defined(UNIX) || defined(WIN3264)
3774 char_u *p;
3775#endif
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003776#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003777 int did_set_shortname;
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003778 mode_t umask_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003779#endif
3780
3781 copybuf = alloc(BUFSIZE + 1);
3782 if (copybuf == NULL)
3783 {
3784 some_error = TRUE; /* out of memory */
3785 goto nobackup;
3786 }
3787
3788 /*
3789 * Try to make the backup in each directory in the 'bdir' option.
3790 *
3791 * Unix semantics has it, that we may have a writable file,
3792 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3793 * - the directory is not writable,
3794 * - the file may be a symbolic link,
3795 * - the file may belong to another user/group, etc.
3796 *
3797 * For these reasons, the existing writable file must be truncated
3798 * and reused. Creation of a backup COPY will be attempted.
3799 */
3800 dirp = p_bdir;
3801 while (*dirp)
3802 {
3803#ifdef UNIX
3804 st_new.st_ino = 0;
3805 st_new.st_dev = 0;
3806 st_new.st_gid = 0;
3807#endif
3808
3809 /*
3810 * Isolate one directory name, using an entry in 'bdir'.
3811 */
3812 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
Bram Moolenaarb782ba42018-08-07 21:39:28 +02003813
3814#if defined(UNIX) || defined(WIN3264)
3815 p = copybuf + STRLEN(copybuf);
3816 if (after_pathsep(copybuf, p) && p[-1] == p[-2])
3817 // Ends with '//', use full path
3818 if ((p = make_percent_swname(copybuf, fname)) != NULL)
3819 {
3820 backup = modname(p, backup_ext, FALSE);
3821 vim_free(p);
3822 }
3823#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003824 rootname = get_file_in_dir(fname, copybuf);
3825 if (rootname == NULL)
3826 {
3827 some_error = TRUE; /* out of memory */
3828 goto nobackup;
3829 }
3830
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003831#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003832 did_set_shortname = FALSE;
3833#endif
3834
3835 /*
3836 * May try twice if 'shortname' not set.
3837 */
3838 for (;;)
3839 {
3840 /*
Bram Moolenaarb782ba42018-08-07 21:39:28 +02003841 * Make the backup file name.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003842 */
Bram Moolenaarb782ba42018-08-07 21:39:28 +02003843 if (backup == NULL)
3844 backup = buf_modname((buf->b_p_sn || buf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00003845 rootname, backup_ext, FALSE);
3846 if (backup == NULL)
3847 {
3848 vim_free(rootname);
3849 some_error = TRUE; /* out of memory */
3850 goto nobackup;
3851 }
3852
3853 /*
3854 * Check if backup file already exists.
3855 */
3856 if (mch_stat((char *)backup, &st_new) >= 0)
3857 {
3858#ifdef UNIX
3859 /*
3860 * Check if backup file is same as original file.
3861 * May happen when modname() gave the same file back.
3862 * E.g. silly link, or file name-length reached.
3863 * If we don't check here, we either ruin the file
3864 * when copying or erase it after writing. jw.
3865 */
3866 if (st_new.st_dev == st_old.st_dev
3867 && st_new.st_ino == st_old.st_ino)
3868 {
Bram Moolenaard23a8232018-02-10 18:45:26 +01003869 VIM_CLEAR(backup); /* no backup file to delete */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870 /*
3871 * may try again with 'shortname' set
3872 */
3873 if (!(buf->b_shortname || buf->b_p_sn))
3874 {
3875 buf->b_shortname = TRUE;
3876 did_set_shortname = TRUE;
3877 continue;
3878 }
3879 /* setting shortname didn't help */
3880 if (did_set_shortname)
3881 buf->b_shortname = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003882 break;
3883 }
3884#endif
3885
3886 /*
3887 * If we are not going to keep the backup file, don't
3888 * delete an existing one, try to use another name.
3889 * Change one character, just before the extension.
3890 */
3891 if (!p_bk)
3892 {
3893 wp = backup + STRLEN(backup) - 1
3894 - STRLEN(backup_ext);
3895 if (wp < backup) /* empty file name ??? */
3896 wp = backup;
3897 *wp = 'z';
3898 while (*wp > 'a'
3899 && mch_stat((char *)backup, &st_new) >= 0)
3900 --*wp;
3901 /* They all exist??? Must be something wrong. */
3902 if (*wp == 'a')
Bram Moolenaard23a8232018-02-10 18:45:26 +01003903 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003904 }
3905 }
3906 break;
3907 }
3908 vim_free(rootname);
3909
3910 /*
3911 * Try to create the backup file
3912 */
3913 if (backup != NULL)
3914 {
3915 /* remove old backup, if present */
3916 mch_remove(backup);
3917 /* Open with O_EXCL to avoid the file being created while
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003918 * we were sleeping (symlink hacker attack?). Reset umask
3919 * if possible to avoid mch_setperm() below. */
3920#ifdef UNIX
3921 umask_save = umask(0);
3922#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003923 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00003924 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
3925 perm & 0777);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003926#ifdef UNIX
3927 (void)umask(umask_save);
3928#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929 if (bfd < 0)
Bram Moolenaard23a8232018-02-10 18:45:26 +01003930 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003931 else
3932 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003933 /* Set file protection same as original file, but
3934 * strip s-bit. Only needed if umask() wasn't used
3935 * above. */
3936#ifndef UNIX
Bram Moolenaar071d4272004-06-13 20:20:40 +00003937 (void)mch_setperm(backup, perm & 0777);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003938#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003939 /*
3940 * Try to set the group of the backup same as the
3941 * original file. If this fails, set the protection
3942 * bits for the group same as the protection bits for
3943 * others.
3944 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003945 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003947 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003948# endif
3949 )
3950 mch_setperm(backup,
3951 (perm & 0707) | ((perm & 07) << 3));
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02003952# if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00003953 mch_copy_sec(fname, backup);
3954# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003955#endif
3956
3957 /*
3958 * copy the file.
3959 */
3960 write_info.bw_fd = bfd;
3961 write_info.bw_buf = copybuf;
3962#ifdef HAS_BW_FLAGS
3963 write_info.bw_flags = FIO_NOCONVERT;
3964#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01003965 while ((write_info.bw_len = read_eintr(fd, copybuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003966 BUFSIZE)) > 0)
3967 {
3968 if (buf_write_bytes(&write_info) == FAIL)
3969 {
3970 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3971 break;
3972 }
3973 ui_breakcheck();
3974 if (got_int)
3975 {
3976 errmsg = (char_u *)_(e_interr);
3977 break;
3978 }
3979 }
3980
3981 if (close(bfd) < 0 && errmsg == NULL)
3982 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3983 if (write_info.bw_len < 0)
3984 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3985#ifdef UNIX
3986 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3987#endif
3988#ifdef HAVE_ACL
3989 mch_set_acl(backup, acl);
3990#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02003991#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00003992 mch_copy_sec(fname, backup);
3993#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003994 break;
3995 }
3996 }
3997 }
3998 nobackup:
3999 close(fd); /* ignore errors for closing read file */
4000 vim_free(copybuf);
4001
4002 if (backup == NULL && errmsg == NULL)
4003 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
4004 /* ignore errors when forceit is TRUE */
4005 if ((some_error || errmsg != NULL) && !forceit)
4006 {
4007 retval = FAIL;
4008 goto fail;
4009 }
4010 errmsg = NULL;
4011 }
4012 else
4013 {
4014 char_u *dirp;
4015 char_u *p;
4016 char_u *rootname;
4017
4018 /*
4019 * Make a backup by renaming the original file.
4020 */
4021 /*
4022 * If 'cpoptions' includes the "W" flag, we don't want to
4023 * overwrite a read-only file. But rename may be possible
4024 * anyway, thus we need an extra check here.
4025 */
4026 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
4027 {
4028 errnum = (char_u *)"E504: ";
4029 errmsg = (char_u *)_(err_readonly);
4030 goto fail;
4031 }
4032
4033 /*
4034 *
4035 * Form the backup file name - change path/fo.o.h to
4036 * path/fo.o.h.bak Try all directories in 'backupdir', first one
4037 * that works is used.
4038 */
4039 dirp = p_bdir;
4040 while (*dirp)
4041 {
4042 /*
4043 * Isolate one directory name and make the backup file name.
4044 */
4045 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
Bram Moolenaarb782ba42018-08-07 21:39:28 +02004046
4047#if defined(UNIX) || defined(WIN3264)
4048 p = IObuff + STRLEN(IObuff);
4049 if (after_pathsep(IObuff, p) && p[-1] == p[-2])
4050 // path ends with '//', use full path
4051 if ((p = make_percent_swname(IObuff, fname)) != NULL)
4052 {
4053 backup = modname(p, backup_ext, FALSE);
4054 vim_free(p);
4055 }
4056#endif
4057 if (backup == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004058 {
Bram Moolenaarb782ba42018-08-07 21:39:28 +02004059 rootname = get_file_in_dir(fname, IObuff);
4060 if (rootname == NULL)
4061 backup = NULL;
4062 else
4063 {
4064 backup = buf_modname(
4065 (buf->b_p_sn || buf->b_shortname),
4066 rootname, backup_ext, FALSE);
4067 vim_free(rootname);
4068 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004069 }
4070
4071 if (backup != NULL)
4072 {
4073 /*
4074 * If we are not going to keep the backup file, don't
4075 * delete an existing one, try to use another name.
4076 * Change one character, just before the extension.
4077 */
4078 if (!p_bk && mch_getperm(backup) >= 0)
4079 {
4080 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
4081 if (p < backup) /* empty file name ??? */
4082 p = backup;
4083 *p = 'z';
4084 while (*p > 'a' && mch_getperm(backup) >= 0)
4085 --*p;
4086 /* They all exist??? Must be something wrong! */
4087 if (*p == 'a')
Bram Moolenaard23a8232018-02-10 18:45:26 +01004088 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004089 }
4090 }
4091 if (backup != NULL)
4092 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004093 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00004094 * Delete any existing backup and move the current version
4095 * to the backup. For safety, we don't remove the backup
4096 * until the write has finished successfully. And if the
4097 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004098 */
4099 /*
4100 * If the renaming of the original file to the backup file
4101 * works, quit here.
4102 */
4103 if (vim_rename(fname, backup) == 0)
4104 break;
4105
Bram Moolenaard23a8232018-02-10 18:45:26 +01004106 VIM_CLEAR(backup); /* don't do the rename below */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004107 }
4108 }
4109 if (backup == NULL && !forceit)
4110 {
4111 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
4112 goto fail;
4113 }
4114 }
4115 }
4116
Bram Moolenaar53076832015-12-31 19:53:21 +01004117#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004118 /* When using ":w!" and the file was read-only: make it writable */
4119 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
4120 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
4121 {
4122 perm |= 0200;
4123 (void)mch_setperm(fname, perm);
4124 made_writable = TRUE;
4125 }
4126#endif
4127
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004128 /* When using ":w!" and writing to the current file, 'readonly' makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00004129 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
4130 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004131 {
4132 buf->b_p_ro = FALSE;
4133#ifdef FEAT_TITLE
4134 need_maketitle = TRUE; /* set window title later */
4135#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004136 status_redraw_all(); /* redraw status lines later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004137 }
4138
4139 if (end > buf->b_ml.ml_line_count)
4140 end = buf->b_ml.ml_line_count;
4141 if (buf->b_ml.ml_flags & ML_EMPTY)
4142 start = end + 1;
4143
4144 /*
4145 * If the original file is being overwritten, there is a small chance that
4146 * we crash in the middle of writing. Therefore the file is preserved now.
4147 * This makes all block numbers positive so that recovery does not need
4148 * the original file.
4149 * Don't do this if there is a backup file and we are exiting.
4150 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004151 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152 && !(exiting && backup != NULL))
4153 {
4154 ml_preserve(buf, FALSE);
4155 if (got_int)
4156 {
4157 errmsg = (char_u *)_(e_interr);
4158 goto restore_backup;
4159 }
4160 }
4161
Bram Moolenaar071d4272004-06-13 20:20:40 +00004162#ifdef VMS
4163 vms_remove_version(fname); /* remove version */
4164#endif
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00004165 /* Default: write the file directly. May write to a temp file for
Bram Moolenaar071d4272004-06-13 20:20:40 +00004166 * multi-byte conversion. */
4167 wfname = fname;
4168
Bram Moolenaar071d4272004-06-13 20:20:40 +00004169 /* Check for forced 'fileencoding' from "++opt=val" argument. */
4170 if (eap != NULL && eap->force_enc != 0)
4171 {
4172 fenc = eap->cmd + eap->force_enc;
4173 fenc = enc_canonize(fenc);
4174 fenc_tofree = fenc;
4175 }
4176 else
4177 fenc = buf->b_p_fenc;
4178
4179 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004180 * Check if the file needs to be converted.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004181 */
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004182 converted = need_conversion(fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004183
4184 /*
4185 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
4186 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
4187 * Prepare the flags for it and allocate bw_conv_buf when needed.
4188 */
4189 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
4190 {
4191 wb_flags = get_fio_flags(fenc);
4192 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
4193 {
4194 /* Need to allocate a buffer to translate into. */
4195 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
4196 write_info.bw_conv_buflen = bufsize * 2;
4197 else /* FIO_UCS4 */
4198 write_info.bw_conv_buflen = bufsize * 4;
4199 write_info.bw_conv_buf
4200 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4201 if (write_info.bw_conv_buf == NULL)
4202 end = 0;
4203 }
4204 }
4205
Bram Moolenaar13505972019-01-24 15:04:48 +01004206#ifdef WIN3264
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
4208 {
4209 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
4210 write_info.bw_conv_buflen = bufsize * 4;
4211 write_info.bw_conv_buf
4212 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4213 if (write_info.bw_conv_buf == NULL)
4214 end = 0;
4215 }
Bram Moolenaar13505972019-01-24 15:04:48 +01004216#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004217
Bram Moolenaar13505972019-01-24 15:04:48 +01004218#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00004219 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
4220 {
4221 write_info.bw_conv_buflen = bufsize * 3;
4222 write_info.bw_conv_buf
4223 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4224 if (write_info.bw_conv_buf == NULL)
4225 end = 0;
4226 }
Bram Moolenaar13505972019-01-24 15:04:48 +01004227#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004228
Bram Moolenaar13505972019-01-24 15:04:48 +01004229#if defined(FEAT_EVAL) || defined(USE_ICONV)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004230 if (converted && wb_flags == 0)
4231 {
Bram Moolenaar13505972019-01-24 15:04:48 +01004232# ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00004233 /*
4234 * Use iconv() conversion when conversion is needed and it's not done
4235 * internally.
4236 */
4237 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
4238 enc_utf8 ? (char_u *)"utf-8" : p_enc);
4239 if (write_info.bw_iconv_fd != (iconv_t)-1)
4240 {
4241 /* We're going to use iconv(), allocate a buffer to convert in. */
4242 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
4243 write_info.bw_conv_buf
4244 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4245 if (write_info.bw_conv_buf == NULL)
4246 end = 0;
4247 write_info.bw_first = TRUE;
4248 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004249# ifdef FEAT_EVAL
Bram Moolenaar13505972019-01-24 15:04:48 +01004250 else
4251# endif
4252# endif
4253
4254# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00004255 /*
4256 * When the file needs to be converted with 'charconvert' after
4257 * writing, write to a temp file instead and let the conversion
4258 * overwrite the original file.
4259 */
4260 if (*p_ccv != NUL)
4261 {
Bram Moolenaare5c421c2015-03-31 13:33:08 +02004262 wfname = vim_tempname('w', FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004263 if (wfname == NULL) /* Can't write without a tempfile! */
4264 {
4265 errmsg = (char_u *)_("E214: Can't find temp file for writing");
4266 goto restore_backup;
4267 }
4268 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004269# endif
Bram Moolenaar13505972019-01-24 15:04:48 +01004270 }
4271#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004272 if (converted && wb_flags == 0
Bram Moolenaar13505972019-01-24 15:04:48 +01004273#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00004274 && write_info.bw_iconv_fd == (iconv_t)-1
Bram Moolenaar13505972019-01-24 15:04:48 +01004275# endif
4276# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277 && wfname == fname
Bram Moolenaar13505972019-01-24 15:04:48 +01004278# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004279 )
4280 {
4281 if (!forceit)
4282 {
4283 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
4284 goto restore_backup;
4285 }
4286 notconverted = TRUE;
4287 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004288
4289 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004290 * If conversion is taking place, we may first pretend to write and check
4291 * for conversion errors. Then loop again to write for real.
4292 * When not doing conversion this writes for real right away.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004293 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004294 for (checking_conversion = TRUE; ; checking_conversion = FALSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004295 {
4296 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004297 * There is no need to check conversion when:
4298 * - there is no conversion
4299 * - we make a backup file, that can be restored in case of conversion
4300 * failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004301 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004302 if (!converted || dobackup)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004303 checking_conversion = FALSE;
4304
4305 if (checking_conversion)
4306 {
4307 /* Make sure we don't write anything. */
4308 fd = -1;
4309 write_info.bw_fd = fd;
4310 }
4311 else
4312 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004313#ifdef HAVE_FTRUNCATE
4314# define TRUNC_ON_OPEN 0
4315#else
4316# define TRUNC_ON_OPEN O_TRUNC
4317#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004318 /*
4319 * Open the file "wfname" for writing.
4320 * We may try to open the file twice: If we can't write to the file
4321 * and forceit is TRUE we delete the existing file and try to
4322 * create a new one. If this still fails we may have lost the
4323 * original file! (this may happen when the user reached his
4324 * quotum for number of files).
4325 * Appending will fail if the file does not exist and forceit is
4326 * FALSE.
4327 */
4328 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
4329 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004330 : (O_CREAT | TRUNC_ON_OPEN))
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004331 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004333 /*
4334 * A forced write will try to create a new file if the old one
4335 * is still readonly. This may also happen when the directory
4336 * is read-only. In that case the mch_remove() will fail.
4337 */
4338 if (errmsg == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004339 {
4340#ifdef UNIX
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004341 stat_T st;
4342
4343 /* Don't delete the file when it's a hard or symbolic link.
4344 */
4345 if ((!newfile && st_old.st_nlink > 1)
4346 || (mch_lstat((char *)fname, &st) == 0
4347 && (st.st_dev != st_old.st_dev
4348 || st.st_ino != st_old.st_ino)))
4349 errmsg = (char_u *)_("E166: Can't open linked file for writing");
4350 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004351#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004352 {
4353 errmsg = (char_u *)_("E212: Can't open file for writing");
4354 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
4355 && perm >= 0)
4356 {
4357#ifdef UNIX
4358 /* we write to the file, thus it should be marked
4359 writable after all */
4360 if (!(perm & 0200))
4361 made_writable = TRUE;
4362 perm |= 0200;
4363 if (st_old.st_uid != getuid()
4364 || st_old.st_gid != getgid())
4365 perm &= 0777;
4366#endif
4367 if (!append) /* don't remove when appending */
4368 mch_remove(wfname);
4369 continue;
4370 }
4371 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004372 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004373
4374restore_backup:
Bram Moolenaar071d4272004-06-13 20:20:40 +00004375 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004376 stat_T st;
4377
Bram Moolenaar071d4272004-06-13 20:20:40 +00004378 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004379 * If we failed to open the file, we don't need a backup.
4380 * Throw it away. If we moved or removed the original file
4381 * try to put the backup in its place.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004382 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004383 if (backup != NULL && wfname == fname)
4384 {
4385 if (backup_copy)
4386 {
4387 /*
4388 * There is a small chance that we removed the
4389 * original, try to move the copy in its place.
4390 * This may not work if the vim_rename() fails.
4391 * In that case we leave the copy around.
4392 */
4393 /* If file does not exist, put the copy in its
4394 * place */
4395 if (mch_stat((char *)fname, &st) < 0)
4396 vim_rename(backup, fname);
4397 /* if original file does exist throw away the copy
4398 */
4399 if (mch_stat((char *)fname, &st) >= 0)
4400 mch_remove(backup);
4401 }
4402 else
4403 {
4404 /* try to put the original file back */
4405 vim_rename(backup, fname);
4406 }
4407 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004409 /* if original file no longer exists give an extra warning
4410 */
4411 if (!newfile && mch_stat((char *)fname, &st) < 0)
4412 end = 0;
4413 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004414
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004415 if (wfname != fname)
4416 vim_free(wfname);
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004417 goto fail;
4418 }
4419 write_info.bw_fd = fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004420
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004421#if defined(UNIX)
4422 {
4423 stat_T st;
4424
4425 /* Double check we are writing the intended file before making
4426 * any changes. */
4427 if (overwriting
4428 && (!dobackup || backup_copy)
4429 && fname == wfname
4430 && perm >= 0
4431 && mch_fstat(fd, &st) == 0
4432 && st.st_ino != st_old.st_ino)
4433 {
4434 close(fd);
4435 errmsg = (char_u *)_("E949: File changed while writing");
4436 goto fail;
4437 }
4438 }
4439#endif
4440#ifdef HAVE_FTRUNCATE
4441 if (!append)
Bram Moolenaar42335f52018-09-13 15:33:43 +02004442 vim_ignored = ftruncate(fd, (off_t)0);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004443#endif
4444
Bram Moolenaard0573012017-10-28 21:11:06 +02004445#if defined(WIN3264)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004446 if (backup != NULL && overwriting && !append)
4447 {
4448 if (backup_copy)
4449 (void)mch_copy_file_attribute(wfname, backup);
4450 else
4451 (void)mch_copy_file_attribute(backup, wfname);
4452 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004454 if (!overwriting && !append)
4455 {
4456 if (buf->b_ffname != NULL)
4457 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
4458 /* Should copy resource fork */
4459 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004460#endif
4461
Bram Moolenaar071d4272004-06-13 20:20:40 +00004462#ifdef FEAT_CRYPT
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004463 if (*buf->b_p_key != NUL && !filtering)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004465 char_u *header;
4466 int header_len;
4467
4468 buf->b_cryptstate = crypt_create_for_writing(
4469 crypt_get_method_nr(buf),
4470 buf->b_p_key, &header, &header_len);
4471 if (buf->b_cryptstate == NULL || header == NULL)
4472 end = 0;
4473 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004474 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004475 /* Write magic number, so that Vim knows how this file is
4476 * encrypted when reading it back. */
4477 write_info.bw_buf = header;
4478 write_info.bw_len = header_len;
4479 write_info.bw_flags = FIO_NOCONVERT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004480 if (buf_write_bytes(&write_info) == FAIL)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004481 end = 0;
4482 wb_flags |= FIO_ENCRYPTED;
4483 vim_free(header);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004485 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004486#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004487 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004488 errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004489
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004490 write_info.bw_buf = buffer;
4491 nchars = 0;
4492
4493 /* use "++bin", "++nobin" or 'binary' */
4494 if (eap != NULL && eap->force_bin != 0)
4495 write_bin = (eap->force_bin == FORCE_BIN);
4496 else
4497 write_bin = buf->b_p_bin;
4498
Bram Moolenaar071d4272004-06-13 20:20:40 +00004499 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004500 * The BOM is written just after the encryption magic number.
4501 * Skip it when appending and the file already existed, the BOM only
4502 * makes sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004503 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004504 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004506 write_info.bw_len = make_bom(buffer, fenc);
4507 if (write_info.bw_len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004508 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004509 /* don't convert, do encryption */
4510 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4511 if (buf_write_bytes(&write_info) == FAIL)
4512 end = 0;
4513 else
4514 nchars += write_info.bw_len;
4515 }
4516 }
4517 write_info.bw_start_lnum = start;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004518
4519#ifdef FEAT_PERSISTENT_UNDO
4520 write_undo_file = (buf->b_p_udf
4521 && overwriting
4522 && !append
4523 && !filtering
4524 && reset_changed
4525 && !checking_conversion);
4526 if (write_undo_file)
4527 /* Prepare for computing the hash value of the text. */
4528 sha256_start(&sha_ctx);
4529#endif
4530
4531 write_info.bw_len = bufsize;
4532#ifdef HAS_BW_FLAGS
4533 write_info.bw_flags = wb_flags;
4534#endif
4535 fileformat = get_fileformat_force(buf, eap);
4536 s = buffer;
4537 len = 0;
4538 for (lnum = start; lnum <= end; ++lnum)
4539 {
4540 /*
4541 * The next while loop is done once for each character written.
4542 * Keep it fast!
4543 */
4544 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
4545#ifdef FEAT_PERSISTENT_UNDO
4546 if (write_undo_file)
4547 sha256_update(&sha_ctx, ptr + 1,
4548 (UINT32_T)(STRLEN(ptr + 1) + 1));
4549#endif
4550 while ((c = *++ptr) != NUL)
4551 {
4552 if (c == NL)
4553 *s = NUL; /* replace newlines with NULs */
4554 else if (c == CAR && fileformat == EOL_MAC)
4555 *s = NL; /* Mac: replace CRs with NLs */
4556 else
4557 *s = c;
4558 ++s;
4559 if (++len != bufsize)
4560 continue;
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004561 if (buf_write_bytes(&write_info) == FAIL)
4562 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004563 end = 0; /* write error: break loop */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004564 break;
4565 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004566 nchars += bufsize;
4567 s = buffer;
4568 len = 0;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004569 write_info.bw_start_lnum = lnum;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004570 }
4571 /* write failed or last line has no EOL: stop here */
4572 if (end == 0
4573 || (lnum == end
4574 && (write_bin || !buf->b_p_fixeol)
4575 && (lnum == buf->b_no_eol_lnum
4576 || (lnum == buf->b_ml.ml_line_count
4577 && !buf->b_p_eol))))
4578 {
4579 ++lnum; /* written the line, count it */
4580 no_eol = TRUE;
4581 break;
4582 }
4583 if (fileformat == EOL_UNIX)
4584 *s++ = NL;
4585 else
4586 {
4587 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4588 if (fileformat == EOL_DOS) /* write CR-NL */
4589 {
4590 if (++len == bufsize)
4591 {
4592 if (buf_write_bytes(&write_info) == FAIL)
4593 {
4594 end = 0; /* write error: break loop */
4595 break;
4596 }
4597 nchars += bufsize;
4598 s = buffer;
4599 len = 0;
4600 }
4601 *s++ = NL;
4602 }
4603 }
4604 if (++len == bufsize && end)
4605 {
4606 if (buf_write_bytes(&write_info) == FAIL)
4607 {
4608 end = 0; /* write error: break loop */
4609 break;
4610 }
4611 nchars += bufsize;
4612 s = buffer;
4613 len = 0;
4614
4615 ui_breakcheck();
4616 if (got_int)
4617 {
4618 end = 0; /* Interrupted, break loop */
4619 break;
4620 }
4621 }
4622#ifdef VMS
4623 /*
4624 * On VMS there is a problem: newlines get added when writing
4625 * blocks at a time. Fix it by writing a line at a time.
4626 * This is much slower!
4627 * Explanation: VAX/DECC RTL insists that records in some RMS
4628 * structures end with a newline (carriage return) character, and
4629 * if they don't it adds one.
4630 * With other RMS structures it works perfect without this fix.
4631 */
4632 if (buf->b_fab_rfm == FAB$C_VFC
4633 || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4634 {
4635 int b2write;
4636
4637 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4638 ? MIN(4096, bufsize)
4639 : MIN(buf->b_fab_mrs, bufsize));
4640
4641 b2write = len;
4642 while (b2write > 0)
4643 {
4644 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4645 if (buf_write_bytes(&write_info) == FAIL)
4646 {
4647 end = 0;
4648 break;
4649 }
4650 b2write -= MIN(b2write, buf->b_fab_mrs);
4651 }
4652 write_info.bw_len = bufsize;
4653 nchars += len;
4654 s = buffer;
4655 len = 0;
4656 }
4657#endif
4658 }
4659 if (len > 0 && end > 0)
4660 {
4661 write_info.bw_len = len;
4662 if (buf_write_bytes(&write_info) == FAIL)
4663 end = 0; /* write error */
4664 nchars += len;
4665 }
4666
4667 /* Stop when writing done or an error was encountered. */
4668 if (!checking_conversion || end == 0)
4669 break;
4670
4671 /* If no error happened until now, writing should be ok, so loop to
4672 * really write the buffer. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004673 }
4674
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004675 /* If we started writing, finish writing. Also when an error was
4676 * encountered. */
4677 if (!checking_conversion)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004678 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004679#if defined(UNIX) && defined(HAVE_FSYNC)
4680 /*
4681 * On many journalling file systems there is a bug that causes both the
4682 * original and the backup file to be lost when halting the system
4683 * right after writing the file. That's because only the meta-data is
4684 * journalled. Syncing the file slows down the system, but assures it
4685 * has been written to disk and we don't lose it.
4686 * For a device do try the fsync() but don't complain if it does not
4687 * work (could be a pipe).
4688 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
4689 */
4690 if (p_fs && fsync(fd) != 0 && !device)
4691 {
Bram Moolenaar7567d0b2017-11-16 23:04:15 +01004692 errmsg = (char_u *)_(e_fsync);
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004693 end = 0;
4694 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004695#endif
4696
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004697#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004698 /* Probably need to set the security context. */
4699 if (!backup_copy)
4700 mch_copy_sec(backup, wfname);
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004701#endif
4702
Bram Moolenaara5792f52005-11-23 21:25:05 +00004703#ifdef UNIX
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004704 /* When creating a new file, set its owner/group to that of the
4705 * original file. Get the new device and inode number. */
4706 if (backup != NULL && !backup_copy)
Bram Moolenaara5792f52005-11-23 21:25:05 +00004707 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004708# ifdef HAVE_FCHOWN
4709 stat_T st;
4710
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004711 /* Don't change the owner when it's already OK, some systems remove
4712 * permission or ACL stuff. */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004713 if (mch_stat((char *)wfname, &st) < 0
4714 || st.st_uid != st_old.st_uid
4715 || st.st_gid != st_old.st_gid)
4716 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004717 /* changing owner might not be possible */
Bram Moolenaar42335f52018-09-13 15:33:43 +02004718 vim_ignored = fchown(fd, st_old.st_uid, -1);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004719 /* if changing group fails clear the group permissions */
4720 if (fchown(fd, -1, st_old.st_gid) == -1 && perm > 0)
4721 perm &= ~070;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004722 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00004723# endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004724 buf_setino(buf);
4725 }
4726 else if (!buf->b_dev_valid)
4727 /* Set the inode when creating a new file. */
4728 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004729#endif
4730
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004731#ifdef UNIX
4732 if (made_writable)
4733 perm &= ~0200; /* reset 'w' bit for security reasons */
4734#endif
4735#ifdef HAVE_FCHMOD
4736 /* set permission of new file same as old file */
4737 if (perm >= 0)
4738 (void)mch_fsetperm(fd, perm);
4739#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004740 if (close(fd) != 0)
4741 {
4742 errmsg = (char_u *)_("E512: Close failed");
4743 end = 0;
4744 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004745
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004746#ifndef HAVE_FCHMOD
4747 /* set permission of new file same as old file */
4748 if (perm >= 0)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004749 (void)mch_setperm(wfname, perm);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004750#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004751#ifdef HAVE_ACL
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004752 /*
4753 * Probably need to set the ACL before changing the user (can't set the
4754 * ACL on a file the user doesn't own).
4755 * On Solaris, with ZFS and the aclmode property set to "discard" (the
4756 * default), chmod() discards all part of a file's ACL that don't
4757 * represent the mode of the file. It's non-trivial for us to discover
4758 * whether we're in that situation, so we simply always re-set the ACL.
4759 */
Bram Moolenaarda412772016-07-14 20:37:07 +02004760# ifndef HAVE_SOLARIS_ZFS_ACL
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004761 if (!backup_copy)
Bram Moolenaarda412772016-07-14 20:37:07 +02004762# endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004763 mch_set_acl(wfname, acl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764#endif
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004765#ifdef FEAT_CRYPT
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004766 if (buf->b_cryptstate != NULL)
4767 {
4768 crypt_free_state(buf->b_cryptstate);
4769 buf->b_cryptstate = NULL;
4770 }
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004771#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004772
Bram Moolenaar13505972019-01-24 15:04:48 +01004773#if defined(FEAT_EVAL)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004774 if (wfname != fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004775 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004776 /*
4777 * The file was written to a temp file, now it needs to be
4778 * converted with 'charconvert' to (overwrite) the output file.
4779 */
4780 if (end != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004782 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc,
4783 fenc, wfname, fname) == FAIL)
4784 {
4785 write_info.bw_conv_error = TRUE;
4786 end = 0;
4787 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004789 mch_remove(wfname);
4790 vim_free(wfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004791 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004793 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004794
4795 if (end == 0)
4796 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004797 /*
4798 * Error encountered.
4799 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004800 if (errmsg == NULL)
4801 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004802 if (write_info.bw_conv_error)
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004803 {
4804 if (write_info.bw_conv_error_lnum == 0)
4805 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
4806 else
4807 {
4808 errmsg_allocated = TRUE;
4809 errmsg = alloc(300);
4810 vim_snprintf((char *)errmsg, 300, _("E513: write error, conversion failed in line %ld (make 'fenc' empty to override)"),
4811 (long)write_info.bw_conv_error_lnum);
4812 }
4813 }
Bram Moolenaar13505972019-01-24 15:04:48 +01004814 else if (got_int)
4815 errmsg = (char_u *)_(e_interr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816 else
Bram Moolenaar13505972019-01-24 15:04:48 +01004817 errmsg = (char_u *)_("E514: write error (file system full?)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004818 }
4819
4820 /*
4821 * If we have a backup file, try to put it in place of the new file,
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004822 * because the new file is probably corrupt. This avoids losing the
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823 * original file when trying to make a backup when writing the file a
4824 * second time.
4825 * When "backup_copy" is set we need to copy the backup over the new
4826 * file. Otherwise rename the backup file.
4827 * If this is OK, don't give the extra warning message.
4828 */
4829 if (backup != NULL)
4830 {
4831 if (backup_copy)
4832 {
4833 /* This may take a while, if we were interrupted let the user
4834 * know we got the message. */
4835 if (got_int)
4836 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01004837 msg(_(e_interr));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004838 out_flush();
4839 }
4840 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4841 {
4842 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004843 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4844 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004845 {
4846 /* copy the file. */
4847 write_info.bw_buf = smallbuf;
4848#ifdef HAS_BW_FLAGS
4849 write_info.bw_flags = FIO_NOCONVERT;
4850#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004851 while ((write_info.bw_len = read_eintr(fd, smallbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 SMBUFSIZE)) > 0)
4853 if (buf_write_bytes(&write_info) == FAIL)
4854 break;
4855
4856 if (close(write_info.bw_fd) >= 0
4857 && write_info.bw_len == 0)
4858 end = 1; /* success */
4859 }
4860 close(fd); /* ignore errors for closing read file */
4861 }
4862 }
4863 else
4864 {
4865 if (vim_rename(backup, fname) == 0)
4866 end = 1;
4867 }
4868 }
4869 goto fail;
4870 }
4871
4872 lnum -= start; /* compute number of written lines */
4873 --no_wait_return; /* may wait for return now */
4874
4875#if !(defined(UNIX) || defined(VMS))
4876 fname = sfname; /* use shortname now, for the messages */
4877#endif
4878 if (!filtering)
4879 {
4880 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4881 c = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004882 if (write_info.bw_conv_error)
4883 {
4884 STRCAT(IObuff, _(" CONVERSION ERROR"));
4885 c = TRUE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004886 if (write_info.bw_conv_error_lnum != 0)
Bram Moolenaara800b422010-06-27 01:15:55 +02004887 vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %ld;"),
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004888 (long)write_info.bw_conv_error_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004889 }
4890 else if (notconverted)
4891 {
4892 STRCAT(IObuff, _("[NOT converted]"));
4893 c = TRUE;
4894 }
4895 else if (converted)
4896 {
4897 STRCAT(IObuff, _("[converted]"));
4898 c = TRUE;
4899 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004900 if (device)
4901 {
4902 STRCAT(IObuff, _("[Device]"));
4903 c = TRUE;
4904 }
4905 else if (newfile)
4906 {
4907 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4908 c = TRUE;
4909 }
4910 if (no_eol)
4911 {
4912 msg_add_eol();
4913 c = TRUE;
4914 }
4915 /* may add [unix/dos/mac] */
4916 if (msg_add_fileformat(fileformat))
4917 c = TRUE;
4918#ifdef FEAT_CRYPT
4919 if (wb_flags & FIO_ENCRYPTED)
4920 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02004921 crypt_append_msg(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004922 c = TRUE;
4923 }
4924#endif
4925 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4926 if (!shortmess(SHM_WRITE))
4927 {
4928 if (append)
4929 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4930 else
4931 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4932 }
4933
Bram Moolenaar32526b32019-01-19 17:43:09 +01004934 set_keep_msg((char_u *)msg_trunc_attr((char *)IObuff, FALSE, 0), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004935 }
4936
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004937 /* When written everything correctly: reset 'modified'. Unless not
4938 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00004939 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00004940 && !write_info.bw_conv_error
Bram Moolenaar13505972019-01-24 15:04:48 +01004941 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004942 {
4943 unchanged(buf, TRUE);
Bram Moolenaar95c526e2017-02-25 14:59:34 +01004944 /* b:changedtick is always incremented in unchanged() but that
Bram Moolenaar086329d2014-10-31 19:51:36 +01004945 * should not trigger a TextChanged event. */
Bram Moolenaar5a093432018-02-10 18:15:19 +01004946 if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf))
4947 buf->b_last_changedtick = CHANGEDTICK(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004948 u_unchanged(buf);
Bram Moolenaar730cde92010-06-27 05:18:54 +02004949 u_update_save_nr(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950 }
4951
4952 /*
4953 * If written to the current file, update the timestamp of the swap file
4954 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4955 */
4956 if (overwriting)
4957 {
4958 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00004959 if (append)
4960 buf->b_flags &= ~BF_NEW;
4961 else
4962 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963 }
4964
4965 /*
4966 * If we kept a backup until now, and we are in patch mode, then we make
4967 * the backup file our 'original' file.
4968 */
4969 if (*p_pm && dobackup)
4970 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +01004971 char *org = (char *)buf_modname((buf->b_p_sn || buf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00004972 fname, p_pm, FALSE);
4973
4974 if (backup != NULL)
4975 {
Bram Moolenaar8767f522016-07-01 17:17:39 +02004976 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004977
4978 /*
4979 * If the original file does not exist yet
4980 * the current backup file becomes the original file
4981 */
4982 if (org == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004983 emsg(_("E205: Patchmode: can't save original file"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004984 else if (mch_stat(org, &st) < 0)
4985 {
4986 vim_rename(backup, (char_u *)org);
Bram Moolenaard23a8232018-02-10 18:45:26 +01004987 VIM_CLEAR(backup); /* don't delete the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004988#ifdef UNIX
4989 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4990#endif
4991 }
4992 }
4993 /*
4994 * If there is no backup file, remember that a (new) file was
4995 * created.
4996 */
4997 else
4998 {
4999 int empty_fd;
5000
5001 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00005002 || (empty_fd = mch_open(org,
5003 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00005004 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005005 emsg(_("E206: patchmode: can't touch empty original file"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005006 else
5007 close(empty_fd);
5008 }
5009 if (org != NULL)
5010 {
5011 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
5012 vim_free(org);
5013 }
5014 }
5015
5016 /*
5017 * Remove the backup unless 'backup' option is set
5018 */
5019 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005020 emsg(_("E207: Can't delete backup file"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005021
Bram Moolenaar071d4272004-06-13 20:20:40 +00005022 goto nofail;
5023
5024 /*
5025 * Finish up. We get here either after failure or success.
5026 */
5027fail:
5028 --no_wait_return; /* may wait for return now */
5029nofail:
5030
5031 /* Done saving, we accept changed buffer warnings again */
5032 buf->b_saving = FALSE;
5033
5034 vim_free(backup);
5035 if (buffer != smallbuf)
5036 vim_free(buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037 vim_free(fenc_tofree);
5038 vim_free(write_info.bw_conv_buf);
Bram Moolenaar13505972019-01-24 15:04:48 +01005039#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00005040 if (write_info.bw_iconv_fd != (iconv_t)-1)
5041 {
5042 iconv_close(write_info.bw_iconv_fd);
5043 write_info.bw_iconv_fd = (iconv_t)-1;
5044 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045#endif
5046#ifdef HAVE_ACL
5047 mch_free_acl(acl);
5048#endif
5049
5050 if (errmsg != NULL)
5051 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005052 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005053
Bram Moolenaar8820b482017-03-16 17:23:31 +01005054 attr = HL_ATTR(HLF_E); /* set highlight for error messages */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005055 msg_add_fname(buf,
5056#ifndef UNIX
5057 sfname
5058#else
5059 fname
5060#endif
5061 ); /* put file name in IObuff with quotes */
5062 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
5063 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
5064 /* If the error message has the form "is ...", put the error number in
5065 * front of the file name. */
5066 if (errnum != NULL)
5067 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00005068 STRMOVE(IObuff + numlen, IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005069 mch_memmove(IObuff, errnum, (size_t)numlen);
5070 }
5071 STRCAT(IObuff, errmsg);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005072 emsg((char *)IObuff);
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005073 if (errmsg_allocated)
5074 vim_free(errmsg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005075
5076 retval = FAIL;
5077 if (end == 0)
5078 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01005079 msg_puts_attr(_("\nWARNING: Original file may be lost or damaged\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080 attr | MSG_HIST);
Bram Moolenaar32526b32019-01-19 17:43:09 +01005081 msg_puts_attr(_("don't quit the editor until the file is successfully written!"),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005082 attr | MSG_HIST);
5083
5084 /* Update the timestamp to avoid an "overwrite changed file"
5085 * prompt when writing again. */
5086 if (mch_stat((char *)fname, &st_old) >= 0)
5087 {
5088 buf_store_time(buf, &st_old, fname);
5089 buf->b_mtime_read = buf->b_mtime;
5090 }
5091 }
5092 }
5093 msg_scroll = msg_save;
5094
Bram Moolenaar55debbe2010-05-23 23:34:36 +02005095#ifdef FEAT_PERSISTENT_UNDO
5096 /*
5097 * When writing the whole file and 'undofile' is set, also write the undo
5098 * file.
5099 */
5100 if (retval == OK && write_undo_file)
5101 {
5102 char_u hash[UNDO_HASH_SIZE];
5103
5104 sha256_finish(&sha_ctx, hash);
5105 u_write_undo(NULL, FALSE, buf, hash);
5106 }
5107#endif
5108
Bram Moolenaar071d4272004-06-13 20:20:40 +00005109#ifdef FEAT_EVAL
5110 if (!should_abort(retval))
5111#else
5112 if (!got_int)
5113#endif
5114 {
5115 aco_save_T aco;
5116
Bram Moolenaar68a33fc2012-04-25 16:50:48 +02005117 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
5118
Bram Moolenaar071d4272004-06-13 20:20:40 +00005119 /*
5120 * Apply POST autocommands.
5121 * Careful: The autocommands may call buf_write() recursively!
5122 */
5123 aucmd_prepbuf(&aco, buf);
5124
5125 if (append)
5126 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
5127 FALSE, curbuf, eap);
5128 else if (filtering)
5129 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
5130 FALSE, curbuf, eap);
5131 else if (reset_changed && whole)
5132 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
5133 FALSE, curbuf, eap);
5134 else
5135 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
5136 FALSE, curbuf, eap);
5137
5138 /* restore curwin/curbuf and a few other things */
5139 aucmd_restbuf(&aco);
5140
5141#ifdef FEAT_EVAL
5142 if (aborting()) /* autocmds may abort script processing */
5143 retval = FALSE;
5144#endif
5145 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005146
5147 got_int |= prev_got_int;
5148
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149 return retval;
5150}
5151
5152/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005153 * Set the name of the current buffer. Use when the buffer doesn't have a
5154 * name and a ":r" or ":w" command with a file name is used.
5155 */
5156 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005157set_rw_fname(char_u *fname, char_u *sfname)
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005158{
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005159 buf_T *buf = curbuf;
5160
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005161 /* It's like the unnamed buffer is deleted.... */
5162 if (curbuf->b_p_bl)
5163 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
5164 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005165#ifdef FEAT_EVAL
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005166 if (aborting()) /* autocmds may abort script processing */
5167 return FAIL;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005168#endif
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005169 if (curbuf != buf)
5170 {
5171 /* We are in another buffer now, don't do the renaming. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005172 emsg(_(e_auchangedbuf));
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005173 return FAIL;
5174 }
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005175
5176 if (setfname(curbuf, fname, sfname, FALSE) == OK)
5177 curbuf->b_flags |= BF_NOTEDITED;
5178
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005179 /* ....and a new named one is created */
5180 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
5181 if (curbuf->b_p_bl)
5182 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005183#ifdef FEAT_EVAL
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005184 if (aborting()) /* autocmds may abort script processing */
5185 return FAIL;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005186#endif
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005187
5188 /* Do filetype detection now if 'filetype' is empty. */
5189 if (*curbuf->b_p_ft == NUL)
5190 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005191 if (au_has_group((char_u *)"filetypedetect"))
Bram Moolenaar1610d052016-06-09 22:53:01 +02005192 (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE, NULL);
Bram Moolenaara3227e22006-03-08 21:32:40 +00005193 do_modelines(0);
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005194 }
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005195
5196 return OK;
5197}
5198
5199/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005200 * Put file name into IObuff with quotes.
5201 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005202 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005203msg_add_fname(buf_T *buf, char_u *fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005204{
5205 if (fname == NULL)
5206 fname = (char_u *)"-stdin-";
5207 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
5208 IObuff[0] = '"';
5209 STRCAT(IObuff, "\" ");
5210}
5211
5212/*
5213 * Append message for text mode to IObuff.
5214 * Return TRUE if something appended.
5215 */
5216 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005217msg_add_fileformat(int eol_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005218{
5219#ifndef USE_CRNL
5220 if (eol_type == EOL_DOS)
5221 {
5222 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
5223 return TRUE;
5224 }
5225#endif
5226#ifndef USE_CR
5227 if (eol_type == EOL_MAC)
5228 {
5229 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
5230 return TRUE;
5231 }
5232#endif
5233#if defined(USE_CRNL) || defined(USE_CR)
5234 if (eol_type == EOL_UNIX)
5235 {
5236 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
5237 return TRUE;
5238 }
5239#endif
5240 return FALSE;
5241}
5242
5243/*
5244 * Append line and character count to IObuff.
5245 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005246 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005247msg_add_lines(
5248 int insert_space,
5249 long lnum,
Bram Moolenaar8767f522016-07-01 17:17:39 +02005250 off_T nchars)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005251{
5252 char_u *p;
5253
5254 p = IObuff + STRLEN(IObuff);
5255
5256 if (insert_space)
5257 *p++ = ' ';
5258 if (shortmess(SHM_LINES))
Bram Moolenaarbde98102016-07-01 20:03:42 +02005259 vim_snprintf((char *)p, IOSIZE - (p - IObuff),
Bram Moolenaar88c86eb2019-01-17 17:13:30 +01005260 "%ldL, %lldC", lnum, (long_long_T)nchars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005261 else
5262 {
Bram Moolenaarda6e8912018-08-21 15:12:14 +02005263 sprintf((char *)p, NGETTEXT("%ld line, ", "%ld lines, ", lnum), lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005264 p += STRLEN(p);
Bram Moolenaarda6e8912018-08-21 15:12:14 +02005265 vim_snprintf((char *)p, IOSIZE - (p - IObuff),
5266 NGETTEXT("%lld character", "%lld characters", nchars),
Bram Moolenaar88c86eb2019-01-17 17:13:30 +01005267 (long_long_T)nchars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005268 }
5269}
5270
5271/*
5272 * Append message for missing line separator to IObuff.
5273 */
5274 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005275msg_add_eol(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005276{
5277 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
5278}
5279
5280/*
5281 * Check modification time of file, before writing to it.
5282 * The size isn't checked, because using a tool like "gzip" takes care of
5283 * using the same timestamp but can't set the size.
5284 */
5285 static int
Bram Moolenaar8767f522016-07-01 17:17:39 +02005286check_mtime(buf_T *buf, stat_T *st)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005287{
5288 if (buf->b_mtime_read != 0
5289 && time_differs((long)st->st_mtime, buf->b_mtime_read))
5290 {
5291 msg_scroll = TRUE; /* don't overwrite messages here */
5292 msg_silent = 0; /* must give this prompt */
5293 /* don't use emsg() here, don't want to flush the buffers */
Bram Moolenaar32526b32019-01-19 17:43:09 +01005294 msg_attr(_("WARNING: The file has been changed since reading it!!!"),
Bram Moolenaar8820b482017-03-16 17:23:31 +01005295 HL_ATTR(HLF_E));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005296 if (ask_yesno((char_u *)_("Do you really want to write to it"),
5297 TRUE) == 'n')
5298 return FAIL;
5299 msg_scroll = FALSE; /* always overwrite the file message now */
5300 }
5301 return OK;
5302}
5303
5304 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005305time_differs(long t1, long t2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005306{
Bram Moolenaar48e330a2016-02-23 14:53:34 +01005307#if defined(__linux__) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005308 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
5309 * the seconds. Since the roundoff is done when flushing the inode, the
5310 * time may change unexpectedly by one second!!! */
5311 return (t1 - t2 > 1 || t2 - t1 > 1);
5312#else
5313 return (t1 != t2);
5314#endif
5315}
5316
5317/*
5318 * Call write() to write a number of bytes to the file.
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005319 * Handles encryption and 'encoding' conversion.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 *
5321 * Return FAIL for failure, OK otherwise.
5322 */
5323 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005324buf_write_bytes(struct bw_info *ip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005325{
5326 int wlen;
5327 char_u *buf = ip->bw_buf; /* data to write */
5328 int len = ip->bw_len; /* length of data */
5329#ifdef HAS_BW_FLAGS
5330 int flags = ip->bw_flags; /* extra flags */
5331#endif
5332
Bram Moolenaar071d4272004-06-13 20:20:40 +00005333 /*
5334 * Skip conversion when writing the crypt magic number or the BOM.
5335 */
5336 if (!(flags & FIO_NOCONVERT))
5337 {
5338 char_u *p;
5339 unsigned c;
5340 int n;
5341
5342 if (flags & FIO_UTF8)
5343 {
5344 /*
5345 * Convert latin1 in the buffer to UTF-8 in the file.
5346 */
5347 p = ip->bw_conv_buf; /* translate to buffer */
5348 for (wlen = 0; wlen < len; ++wlen)
5349 p += utf_char2bytes(buf[wlen], p);
5350 buf = ip->bw_conv_buf;
5351 len = (int)(p - ip->bw_conv_buf);
5352 }
5353 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
5354 {
5355 /*
5356 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
5357 * Latin1 chars in the file.
5358 */
5359 if (flags & FIO_LATIN1)
5360 p = buf; /* translate in-place (can only get shorter) */
5361 else
5362 p = ip->bw_conv_buf; /* translate to buffer */
5363 for (wlen = 0; wlen < len; wlen += n)
5364 {
5365 if (wlen == 0 && ip->bw_restlen != 0)
5366 {
5367 int l;
5368
5369 /* Use remainder of previous call. Append the start of
5370 * buf[] to get a full sequence. Might still be too
5371 * short! */
5372 l = CONV_RESTLEN - ip->bw_restlen;
5373 if (l > len)
5374 l = len;
5375 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005376 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005377 if (n > ip->bw_restlen + len)
5378 {
5379 /* We have an incomplete byte sequence at the end to
5380 * be written. We can't convert it without the
5381 * remaining bytes. Keep them for the next call. */
5382 if (ip->bw_restlen + len > CONV_RESTLEN)
5383 return FAIL;
5384 ip->bw_restlen += len;
5385 break;
5386 }
5387 if (n > 1)
5388 c = utf_ptr2char(ip->bw_rest);
5389 else
5390 c = ip->bw_rest[0];
5391 if (n >= ip->bw_restlen)
5392 {
5393 n -= ip->bw_restlen;
5394 ip->bw_restlen = 0;
5395 }
5396 else
5397 {
5398 ip->bw_restlen -= n;
5399 mch_memmove(ip->bw_rest, ip->bw_rest + n,
5400 (size_t)ip->bw_restlen);
5401 n = 0;
5402 }
5403 }
5404 else
5405 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005406 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 if (n > len - wlen)
5408 {
5409 /* We have an incomplete byte sequence at the end to
5410 * be written. We can't convert it without the
5411 * remaining bytes. Keep them for the next call. */
5412 if (len - wlen > CONV_RESTLEN)
5413 return FAIL;
5414 ip->bw_restlen = len - wlen;
5415 mch_memmove(ip->bw_rest, buf + wlen,
5416 (size_t)ip->bw_restlen);
5417 break;
5418 }
5419 if (n > 1)
5420 c = utf_ptr2char(buf + wlen);
5421 else
5422 c = buf[wlen];
5423 }
5424
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005425 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error)
5426 {
5427 ip->bw_conv_error = TRUE;
5428 ip->bw_conv_error_lnum = ip->bw_start_lnum;
5429 }
5430 if (c == NL)
5431 ++ip->bw_start_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005432 }
5433 if (flags & FIO_LATIN1)
5434 len = (int)(p - buf);
5435 else
5436 {
5437 buf = ip->bw_conv_buf;
5438 len = (int)(p - ip->bw_conv_buf);
5439 }
5440 }
5441
Bram Moolenaar13505972019-01-24 15:04:48 +01005442#ifdef WIN3264
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443 else if (flags & FIO_CODEPAGE)
5444 {
5445 /*
5446 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
5447 * codepage.
5448 */
5449 char_u *from;
5450 size_t fromlen;
5451 char_u *to;
5452 int u8c;
5453 BOOL bad = FALSE;
5454 int needed;
5455
5456 if (ip->bw_restlen > 0)
5457 {
5458 /* Need to concatenate the remainder of the previous call and
5459 * the bytes of the current call. Use the end of the
5460 * conversion buffer for this. */
5461 fromlen = len + ip->bw_restlen;
5462 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5463 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5464 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5465 }
5466 else
5467 {
5468 from = buf;
5469 fromlen = len;
5470 }
5471
5472 to = ip->bw_conv_buf;
5473 if (enc_utf8)
5474 {
5475 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
5476 * The buffer has been allocated to be big enough. */
5477 while (fromlen > 0)
5478 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005479 n = (int)utf_ptr2len_len(from, (int)fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480 if (n > (int)fromlen) /* incomplete byte sequence */
5481 break;
5482 u8c = utf_ptr2char(from);
5483 *to++ = (u8c & 0xff);
5484 *to++ = (u8c >> 8);
5485 fromlen -= n;
5486 from += n;
5487 }
5488
5489 /* Copy remainder to ip->bw_rest[] to be used for the next
5490 * call. */
5491 if (fromlen > CONV_RESTLEN)
5492 {
5493 /* weird overlong sequence */
5494 ip->bw_conv_error = TRUE;
5495 return FAIL;
5496 }
5497 mch_memmove(ip->bw_rest, from, fromlen);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005498 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005499 }
5500 else
5501 {
5502 /* Convert from enc_codepage to UCS-2, to the start of the
5503 * buffer. The buffer has been allocated to be big enough. */
5504 ip->bw_restlen = 0;
5505 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005506 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507 NULL, 0);
5508 if (needed == 0)
5509 {
5510 /* When conversion fails there may be a trailing byte. */
5511 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005512 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005513 NULL, 0);
5514 if (needed == 0)
5515 {
5516 /* Conversion doesn't work. */
5517 ip->bw_conv_error = TRUE;
5518 return FAIL;
5519 }
5520 /* Save the trailing byte for the next call. */
5521 ip->bw_rest[0] = from[fromlen - 1];
5522 ip->bw_restlen = 1;
5523 }
5524 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005525 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005526 (LPWSTR)to, needed);
5527 if (needed == 0)
5528 {
5529 /* Safety check: Conversion doesn't work. */
5530 ip->bw_conv_error = TRUE;
5531 return FAIL;
5532 }
5533 to += needed * 2;
5534 }
5535
5536 fromlen = to - ip->bw_conv_buf;
5537 buf = to;
Bram Moolenaar13505972019-01-24 15:04:48 +01005538# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005539 if (FIO_GET_CP(flags) == CP_UTF8)
5540 {
5541 /* Convert from UCS-2 to UTF-8, using the remainder of the
5542 * conversion buffer. Fails when out of space. */
5543 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
5544 {
5545 u8c = *from++;
5546 u8c += (*from++ << 8);
5547 to += utf_char2bytes(u8c, to);
5548 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
5549 {
5550 ip->bw_conv_error = TRUE;
5551 return FAIL;
5552 }
5553 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005554 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005555 }
5556 else
Bram Moolenaar13505972019-01-24 15:04:48 +01005557# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005558 {
5559 /* Convert from UCS-2 to the codepage, using the remainder of
5560 * the conversion buffer. If the conversion uses the default
5561 * character "0", the data doesn't fit in this encoding, so
5562 * fail. */
5563 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5564 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005565 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0,
5566 &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005567 if (bad)
5568 {
5569 ip->bw_conv_error = TRUE;
5570 return FAIL;
5571 }
5572 }
5573 }
Bram Moolenaar13505972019-01-24 15:04:48 +01005574#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005575
Bram Moolenaar13505972019-01-24 15:04:48 +01005576#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577 else if (flags & FIO_MACROMAN)
5578 {
5579 /*
5580 * Convert UTF-8 or latin1 to Apple MacRoman.
5581 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005582 char_u *from;
5583 size_t fromlen;
5584
5585 if (ip->bw_restlen > 0)
5586 {
5587 /* Need to concatenate the remainder of the previous call and
5588 * the bytes of the current call. Use the end of the
5589 * conversion buffer for this. */
5590 fromlen = len + ip->bw_restlen;
5591 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5592 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5593 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5594 }
5595 else
5596 {
5597 from = buf;
5598 fromlen = len;
5599 }
5600
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005601 if (enc2macroman(from, fromlen,
5602 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5603 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005604 {
5605 ip->bw_conv_error = TRUE;
5606 return FAIL;
5607 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005608 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005609 }
Bram Moolenaar13505972019-01-24 15:04:48 +01005610#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005611
Bram Moolenaar13505972019-01-24 15:04:48 +01005612#ifdef USE_ICONV
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 if (ip->bw_iconv_fd != (iconv_t)-1)
5614 {
5615 const char *from;
5616 size_t fromlen;
5617 char *to;
5618 size_t tolen;
5619
5620 /* Convert with iconv(). */
5621 if (ip->bw_restlen > 0)
5622 {
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005623 char *fp;
5624
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 /* Need to concatenate the remainder of the previous call and
5626 * the bytes of the current call. Use the end of the
5627 * conversion buffer for this. */
5628 fromlen = len + ip->bw_restlen;
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005629 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5630 mch_memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
5631 mch_memmove(fp + ip->bw_restlen, buf, (size_t)len);
5632 from = fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005633 tolen = ip->bw_conv_buflen - fromlen;
5634 }
5635 else
5636 {
5637 from = (const char *)buf;
5638 fromlen = len;
5639 tolen = ip->bw_conv_buflen;
5640 }
5641 to = (char *)ip->bw_conv_buf;
5642
5643 if (ip->bw_first)
5644 {
5645 size_t save_len = tolen;
5646
5647 /* output the initial shift state sequence */
5648 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5649
5650 /* There is a bug in iconv() on Linux (which appears to be
5651 * wide-spread) which sets "to" to NULL and messes up "tolen".
5652 */
5653 if (to == NULL)
5654 {
5655 to = (char *)ip->bw_conv_buf;
5656 tolen = save_len;
5657 }
5658 ip->bw_first = FALSE;
5659 }
5660
5661 /*
5662 * If iconv() has an error or there is not enough room, fail.
5663 */
5664 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5665 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5666 || fromlen > CONV_RESTLEN)
5667 {
5668 ip->bw_conv_error = TRUE;
5669 return FAIL;
5670 }
5671
5672 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5673 if (fromlen > 0)
5674 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5675 ip->bw_restlen = (int)fromlen;
5676
5677 buf = ip->bw_conv_buf;
5678 len = (int)((char_u *)to - ip->bw_conv_buf);
5679 }
Bram Moolenaar13505972019-01-24 15:04:48 +01005680#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005681 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005682
Bram Moolenaare6bf6552017-06-27 22:11:51 +02005683 if (ip->bw_fd < 0)
5684 /* Only checking conversion, which is OK if we get here. */
5685 return OK;
5686
Bram Moolenaar071d4272004-06-13 20:20:40 +00005687#ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005688 if (flags & FIO_ENCRYPTED)
5689 {
5690 /* Encrypt the data. Do it in-place if possible, otherwise use an
5691 * allocated buffer. */
Bram Moolenaar987411d2019-01-18 22:48:34 +01005692# ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005693 if (crypt_works_inplace(ip->bw_buffer->b_cryptstate))
5694 {
Bram Moolenaar987411d2019-01-18 22:48:34 +01005695# endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005696 crypt_encode_inplace(ip->bw_buffer->b_cryptstate, buf, len);
Bram Moolenaar987411d2019-01-18 22:48:34 +01005697# ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005698 }
5699 else
5700 {
5701 char_u *outbuf;
5702
5703 len = crypt_encode_alloc(curbuf->b_cryptstate, buf, len, &outbuf);
5704 if (len == 0)
5705 return OK; /* Crypt layer is buffering, will flush later. */
5706 wlen = write_eintr(ip->bw_fd, outbuf, len);
5707 vim_free(outbuf);
5708 return (wlen < len) ? FAIL : OK;
5709 }
Bram Moolenaar987411d2019-01-18 22:48:34 +01005710# endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005711 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005712#endif
5713
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005714 wlen = write_eintr(ip->bw_fd, buf, len);
5715 return (wlen < len) ? FAIL : OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005716}
5717
Bram Moolenaar071d4272004-06-13 20:20:40 +00005718/*
5719 * Convert a Unicode character to bytes.
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005720 * Return TRUE for an error, FALSE when it's OK.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721 */
5722 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005723ucs2bytes(
5724 unsigned c, /* in: character */
5725 char_u **pp, /* in/out: pointer to result */
5726 int flags) /* FIO_ flags */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005727{
5728 char_u *p = *pp;
5729 int error = FALSE;
5730 int cc;
5731
5732
5733 if (flags & FIO_UCS4)
5734 {
5735 if (flags & FIO_ENDIAN_L)
5736 {
5737 *p++ = c;
5738 *p++ = (c >> 8);
5739 *p++ = (c >> 16);
5740 *p++ = (c >> 24);
5741 }
5742 else
5743 {
5744 *p++ = (c >> 24);
5745 *p++ = (c >> 16);
5746 *p++ = (c >> 8);
5747 *p++ = c;
5748 }
5749 }
5750 else if (flags & (FIO_UCS2 | FIO_UTF16))
5751 {
5752 if (c >= 0x10000)
5753 {
5754 if (flags & FIO_UTF16)
5755 {
5756 /* Make two words, ten bits of the character in each. First
5757 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5758 c -= 0x10000;
5759 if (c >= 0x100000)
5760 error = TRUE;
5761 cc = ((c >> 10) & 0x3ff) + 0xd800;
5762 if (flags & FIO_ENDIAN_L)
5763 {
5764 *p++ = cc;
5765 *p++ = ((unsigned)cc >> 8);
5766 }
5767 else
5768 {
5769 *p++ = ((unsigned)cc >> 8);
5770 *p++ = cc;
5771 }
5772 c = (c & 0x3ff) + 0xdc00;
5773 }
5774 else
5775 error = TRUE;
5776 }
5777 if (flags & FIO_ENDIAN_L)
5778 {
5779 *p++ = c;
5780 *p++ = (c >> 8);
5781 }
5782 else
5783 {
5784 *p++ = (c >> 8);
5785 *p++ = c;
5786 }
5787 }
5788 else /* Latin1 */
5789 {
5790 if (c >= 0x100)
5791 {
5792 error = TRUE;
5793 *p++ = 0xBF;
5794 }
5795 else
5796 *p++ = c;
5797 }
5798
5799 *pp = p;
5800 return error;
5801}
5802
5803/*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005804 * Return TRUE if file encoding "fenc" requires conversion from or to
5805 * 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005806 */
5807 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005808need_conversion(char_u *fenc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005809{
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005810 int same_encoding;
5811 int enc_flags;
5812 int fenc_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005814 if (*fenc == NUL || STRCMP(p_enc, fenc) == 0)
Bram Moolenaar442b4222010-05-24 21:34:22 +02005815 {
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005816 same_encoding = TRUE;
Bram Moolenaar442b4222010-05-24 21:34:22 +02005817 fenc_flags = 0;
5818 }
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005819 else
5820 {
5821 /* Ignore difference between "ansi" and "latin1", "ucs-4" and
5822 * "ucs-4be", etc. */
5823 enc_flags = get_fio_flags(p_enc);
5824 fenc_flags = get_fio_flags(fenc);
5825 same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
5826 }
5827 if (same_encoding)
5828 {
5829 /* Specified encoding matches with 'encoding'. This requires
5830 * conversion when 'encoding' is Unicode but not UTF-8. */
5831 return enc_unicode != 0;
5832 }
5833
5834 /* Encodings differ. However, conversion is not needed when 'enc' is any
5835 * Unicode encoding and the file is UTF-8. */
5836 return !(enc_utf8 && fenc_flags == FIO_UTF8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005837}
5838
5839/*
5840 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5841 * internal conversion.
5842 * if "ptr" is an empty string, use 'encoding'.
5843 */
5844 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005845get_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005846{
5847 int prop;
5848
5849 if (*ptr == NUL)
5850 ptr = p_enc;
5851
5852 prop = enc_canon_props(ptr);
5853 if (prop & ENC_UNICODE)
5854 {
5855 if (prop & ENC_2BYTE)
5856 {
5857 if (prop & ENC_ENDIAN_L)
5858 return FIO_UCS2 | FIO_ENDIAN_L;
5859 return FIO_UCS2;
5860 }
5861 if (prop & ENC_4BYTE)
5862 {
5863 if (prop & ENC_ENDIAN_L)
5864 return FIO_UCS4 | FIO_ENDIAN_L;
5865 return FIO_UCS4;
5866 }
5867 if (prop & ENC_2WORD)
5868 {
5869 if (prop & ENC_ENDIAN_L)
5870 return FIO_UTF16 | FIO_ENDIAN_L;
5871 return FIO_UTF16;
5872 }
5873 return FIO_UTF8;
5874 }
5875 if (prop & ENC_LATIN1)
5876 return FIO_LATIN1;
5877 /* must be ENC_DBCS, requires iconv() */
5878 return 0;
5879}
5880
5881#ifdef WIN3264
5882/*
5883 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5884 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5885 * Used for conversion between 'encoding' and 'fileencoding'.
5886 */
5887 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005888get_win_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005889{
5890 int cp;
5891
5892 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5893 if (!enc_utf8 && enc_codepage <= 0)
5894 return 0;
5895
5896 cp = encname2codepage(ptr);
5897 if (cp == 0)
5898 {
5899# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5900 if (STRCMP(ptr, "utf-8") == 0)
5901 cp = CP_UTF8;
5902 else
5903# endif
5904 return 0;
5905 }
5906 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5907}
5908#endif
5909
Bram Moolenaard0573012017-10-28 21:11:06 +02005910#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005911/*
5912 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5913 * needed for the internal conversion to/from utf-8 or latin1.
5914 */
5915 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005916get_mac_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005917{
5918 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5919 && (enc_canon_props(ptr) & ENC_MACROMAN))
5920 return FIO_MACROMAN;
5921 return 0;
5922}
5923#endif
5924
5925/*
5926 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5927 * "size" must be at least 2.
5928 * Return the name of the encoding and set "*lenp" to the length.
5929 * Returns NULL when no BOM found.
5930 */
5931 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005932check_for_bom(
5933 char_u *p,
5934 long size,
5935 int *lenp,
5936 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005937{
5938 char *name = NULL;
5939 int len = 2;
5940
5941 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
Bram Moolenaaree0f5a62008-07-24 20:09:16 +00005942 && (flags == FIO_ALL || flags == FIO_UTF8 || flags == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005943 {
5944 name = "utf-8"; /* EF BB BF */
5945 len = 3;
5946 }
5947 else if (p[0] == 0xff && p[1] == 0xfe)
5948 {
5949 if (size >= 4 && p[2] == 0 && p[3] == 0
5950 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5951 {
5952 name = "ucs-4le"; /* FF FE 00 00 */
5953 len = 4;
5954 }
Bram Moolenaar223a1892008-11-11 20:57:11 +00005955 else if (flags == (FIO_UCS2 | FIO_ENDIAN_L))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005956 name = "ucs-2le"; /* FF FE */
Bram Moolenaar223a1892008-11-11 20:57:11 +00005957 else if (flags == FIO_ALL || flags == (FIO_UTF16 | FIO_ENDIAN_L))
5958 /* utf-16le is preferred, it also works for ucs-2le text */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005959 name = "utf-16le"; /* FF FE */
5960 }
5961 else if (p[0] == 0xfe && p[1] == 0xff
5962 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5963 {
Bram Moolenaarffd82c52008-02-20 17:15:26 +00005964 /* Default to utf-16, it works also for ucs-2 text. */
5965 if (flags == FIO_UCS2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005966 name = "ucs-2"; /* FE FF */
Bram Moolenaarffd82c52008-02-20 17:15:26 +00005967 else
5968 name = "utf-16"; /* FE FF */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005969 }
5970 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5971 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5972 {
5973 name = "ucs-4"; /* 00 00 FE FF */
5974 len = 4;
5975 }
5976
5977 *lenp = len;
5978 return (char_u *)name;
5979}
5980
5981/*
5982 * Generate a BOM in "buf[4]" for encoding "name".
5983 * Return the length of the BOM (zero when no BOM).
5984 */
5985 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005986make_bom(char_u *buf, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005987{
5988 int flags;
5989 char_u *p;
5990
5991 flags = get_fio_flags(name);
5992
5993 /* Can't put a BOM in a non-Unicode file. */
5994 if (flags == FIO_LATIN1 || flags == 0)
5995 return 0;
5996
5997 if (flags == FIO_UTF8) /* UTF-8 */
5998 {
5999 buf[0] = 0xef;
6000 buf[1] = 0xbb;
6001 buf[2] = 0xbf;
6002 return 3;
6003 }
6004 p = buf;
6005 (void)ucs2bytes(0xfeff, &p, flags);
6006 return (int)(p - buf);
6007}
Bram Moolenaar071d4272004-06-13 20:20:40 +00006008
6009/*
6010 * Try to find a shortname by comparing the fullname with the current
6011 * directory.
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006012 * Returns "full_path" or pointer into "full_path" if shortened.
6013 */
6014 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006015shorten_fname1(char_u *full_path)
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006016{
Bram Moolenaard9462e32011-04-11 21:35:11 +02006017 char_u *dirname;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006018 char_u *p = full_path;
6019
Bram Moolenaard9462e32011-04-11 21:35:11 +02006020 dirname = alloc(MAXPATHL);
6021 if (dirname == NULL)
6022 return full_path;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006023 if (mch_dirname(dirname, MAXPATHL) == OK)
6024 {
6025 p = shorten_fname(full_path, dirname);
6026 if (p == NULL || *p == NUL)
6027 p = full_path;
6028 }
Bram Moolenaard9462e32011-04-11 21:35:11 +02006029 vim_free(dirname);
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006030 return p;
6031}
6032
6033/*
6034 * Try to find a shortname by comparing the fullname with the current
6035 * directory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006036 * Returns NULL if not shorter name possible, pointer into "full_path"
6037 * otherwise.
6038 */
6039 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006040shorten_fname(char_u *full_path, char_u *dir_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041{
6042 int len;
6043 char_u *p;
6044
6045 if (full_path == NULL)
6046 return NULL;
6047 len = (int)STRLEN(dir_name);
6048 if (fnamencmp(dir_name, full_path, len) == 0)
6049 {
6050 p = full_path + len;
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006051#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006052 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006053 * MSWIN: when a file is in the root directory, dir_name will end in a
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054 * slash, since C: by itself does not define a specific dir. In this
6055 * case p may already be correct. <negri>
6056 */
6057 if (!((len > 2) && (*(p - 2) == ':')))
6058#endif
6059 {
6060 if (vim_ispathsep(*p))
6061 ++p;
6062#ifndef VMS /* the path separator is always part of the path */
6063 else
6064 p = NULL;
6065#endif
6066 }
6067 }
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006068#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069 /*
6070 * When using a file in the current drive, remove the drive name:
6071 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
6072 * a floppy from "A:\dir" to "B:\dir".
6073 */
6074 else if (len > 3
6075 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
6076 && full_path[1] == ':'
6077 && vim_ispathsep(full_path[2]))
6078 p = full_path + 2;
6079#endif
6080 else
6081 p = NULL;
6082 return p;
6083}
6084
6085/*
Bram Moolenaara796d462018-05-01 14:30:36 +02006086 * Shorten filename of a buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006087 * When "force" is TRUE: Use full path from now on for files currently being
6088 * edited, both for file name and swap file name. Try to shorten the file
6089 * names a bit, if safe to do so.
6090 * When "force" is FALSE: Only try to shorten absolute file names.
6091 * For buffers that have buftype "nofile" or "scratch": never change the file
6092 * name.
6093 */
6094 void
Bram Moolenaara796d462018-05-01 14:30:36 +02006095shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
6096{
6097 char_u *p;
6098
6099 if (buf->b_fname != NULL
6100#ifdef FEAT_QUICKFIX
6101 && !bt_nofile(buf)
6102#endif
6103 && !path_with_url(buf->b_fname)
6104 && (force
6105 || buf->b_sfname == NULL
6106 || mch_isFullName(buf->b_sfname)))
6107 {
Bram Moolenaar3d6014f2018-10-11 19:27:47 +02006108 if (buf->b_sfname != buf->b_ffname)
6109 VIM_CLEAR(buf->b_sfname);
Bram Moolenaara796d462018-05-01 14:30:36 +02006110 p = shorten_fname(buf->b_ffname, dirname);
6111 if (p != NULL)
6112 {
6113 buf->b_sfname = vim_strsave(p);
6114 buf->b_fname = buf->b_sfname;
6115 }
6116 if (p == NULL || buf->b_fname == NULL)
6117 buf->b_fname = buf->b_ffname;
6118 }
6119}
6120
6121/*
6122 * Shorten filenames for all buffers.
6123 */
6124 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006125shorten_fnames(int force)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006126{
6127 char_u dirname[MAXPATHL];
6128 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006129
6130 mch_dirname(dirname, MAXPATHL);
Bram Moolenaar29323592016-07-24 22:04:11 +02006131 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006132 {
Bram Moolenaara796d462018-05-01 14:30:36 +02006133 shorten_buf_fname(buf, dirname, force);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006134
6135 /* Always make the swap file name a full path, a "nofile" buffer may
6136 * also have a swap file. */
6137 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006138 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006139 status_redraw_all();
Bram Moolenaar49d7bf12006-02-17 21:45:41 +00006140 redraw_tabline = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006141}
6142
6143#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
6144 || defined(FEAT_GUI_MSWIN) \
6145 || defined(FEAT_GUI_MAC) \
6146 || defined(PROTO)
6147/*
6148 * Shorten all filenames in "fnames[count]" by current directory.
6149 */
6150 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006151shorten_filenames(char_u **fnames, int count)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006152{
6153 int i;
6154 char_u dirname[MAXPATHL];
6155 char_u *p;
6156
6157 if (fnames == NULL || count < 1)
6158 return;
6159 mch_dirname(dirname, sizeof(dirname));
6160 for (i = 0; i < count; ++i)
6161 {
6162 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
6163 {
6164 /* shorten_fname() returns pointer in given "fnames[i]". If free
6165 * "fnames[i]" first, "p" becomes invalid. So we need to copy
6166 * "p" first then free fnames[i]. */
6167 p = vim_strsave(p);
6168 vim_free(fnames[i]);
6169 fnames[i] = p;
6170 }
6171 }
6172}
6173#endif
6174
6175/*
Bram Moolenaarb782ba42018-08-07 21:39:28 +02006176 * Add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
Bram Moolenaar071d4272004-06-13 20:20:40 +00006177 * fo_o_h.ext for MSDOS or when shortname option set.
6178 *
6179 * Assumed that fname is a valid name found in the filesystem we assure that
6180 * the return value is a different name and ends in 'ext'.
6181 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
6182 * characters otherwise.
6183 * Space for the returned name is allocated, must be freed later.
6184 * Returns NULL when out of memory.
6185 */
6186 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006187modname(
6188 char_u *fname,
6189 char_u *ext,
6190 int prepend_dot) /* may prepend a '.' to file name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006191{
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006192 return buf_modname((curbuf->b_p_sn || curbuf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00006193 fname, ext, prepend_dot);
6194}
6195
6196 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006197buf_modname(
6198 int shortname, /* use 8.3 file name */
6199 char_u *fname,
6200 char_u *ext,
6201 int prepend_dot) /* may prepend a '.' to file name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006202{
6203 char_u *retval;
6204 char_u *s;
6205 char_u *e;
6206 char_u *ptr;
6207 int fnamelen, extlen;
6208
6209 extlen = (int)STRLEN(ext);
6210
6211 /*
6212 * If there is no file name we must get the name of the current directory
6213 * (we need the full path in case :cd is used).
6214 */
6215 if (fname == NULL || *fname == NUL)
6216 {
6217 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
6218 if (retval == NULL)
6219 return NULL;
6220 if (mch_dirname(retval, MAXPATHL) == FAIL ||
6221 (fnamelen = (int)STRLEN(retval)) == 0)
6222 {
6223 vim_free(retval);
6224 return NULL;
6225 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006226 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006227 {
6228 retval[fnamelen++] = PATHSEP;
6229 retval[fnamelen] = NUL;
6230 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006231 prepend_dot = FALSE; /* nothing to prepend a dot to */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006232 }
6233 else
6234 {
6235 fnamelen = (int)STRLEN(fname);
6236 retval = alloc((unsigned)(fnamelen + extlen + 3));
6237 if (retval == NULL)
6238 return NULL;
6239 STRCPY(retval, fname);
6240#ifdef VMS
6241 vms_remove_version(retval); /* we do not need versions here */
6242#endif
6243 }
6244
6245 /*
6246 * search backwards until we hit a '/', '\' or ':' replacing all '.'
6247 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
6248 * Then truncate what is after the '/', '\' or ':' to 8 characters for
6249 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
6250 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006251 for (ptr = retval + fnamelen; ptr > retval; MB_PTR_BACK(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006252 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253 if (*ext == '.'
Bram Moolenaare60acc12011-05-10 16:41:25 +02006254#ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006255 && (!USE_LONG_FNAME || shortname)
Bram Moolenaare60acc12011-05-10 16:41:25 +02006256#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006257 && shortname
Bram Moolenaare60acc12011-05-10 16:41:25 +02006258#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006259 )
6260 if (*ptr == '.') /* replace '.' by '_' */
6261 *ptr = '_';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006262 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006263 {
6264 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006265 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006266 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006267 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006268
6269 /* the file name has at most BASENAMELEN characters. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006270 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
6271 ptr[BASENAMELEN] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006272
6273 s = ptr + STRLEN(ptr);
6274
6275 /*
6276 * For 8.3 file names we may have to reduce the length.
6277 */
6278#ifdef USE_LONG_FNAME
6279 if (!USE_LONG_FNAME || shortname)
6280#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006281 if (shortname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006282#endif
6283 {
6284 /*
6285 * If there is no file name, or the file name ends in '/', and the
6286 * extension starts with '.', put a '_' before the dot, because just
6287 * ".ext" is invalid.
6288 */
6289 if (fname == NULL || *fname == NUL
6290 || vim_ispathsep(fname[STRLEN(fname) - 1]))
6291 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006292 if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006293 *s++ = '_';
6294 }
6295 /*
6296 * If the extension starts with '.', truncate the base name at 8
6297 * characters
6298 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006299 else if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006300 {
Bram Moolenaar78a15312009-05-15 19:33:18 +00006301 if ((size_t)(s - ptr) > (size_t)8)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006302 {
6303 s = ptr + 8;
6304 *s = '\0';
6305 }
6306 }
6307 /*
6308 * If the extension doesn't start with '.', and the file name
6309 * doesn't have an extension yet, append a '.'
6310 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006311 else if ((e = vim_strchr(ptr, '.')) == NULL)
6312 *s++ = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006313 /*
6314 * If the extension doesn't start with '.', and there already is an
Bram Moolenaar7263a772007-05-10 17:35:54 +00006315 * extension, it may need to be truncated
Bram Moolenaar071d4272004-06-13 20:20:40 +00006316 */
6317 else if ((int)STRLEN(e) + extlen > 4)
6318 s = e + 4 - extlen;
6319 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +01006320#if defined(USE_LONG_FNAME) || defined(WIN3264)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006321 /*
6322 * If there is no file name, and the extension starts with '.', put a
6323 * '_' before the dot, because just ".ext" may be invalid if it's on a
6324 * FAT partition, and on HPFS it doesn't matter.
6325 */
6326 else if ((fname == NULL || *fname == NUL) && *ext == '.')
6327 *s++ = '_';
6328#endif
6329
6330 /*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006331 * Append the extension.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006332 * ext can start with '.' and cannot exceed 3 more characters.
6333 */
6334 STRCPY(s, ext);
6335
Bram Moolenaar071d4272004-06-13 20:20:40 +00006336 /*
6337 * Prepend the dot.
6338 */
Bram Moolenaare60acc12011-05-10 16:41:25 +02006339 if (prepend_dot && !shortname && *(e = gettail(retval)) != '.'
Bram Moolenaar071d4272004-06-13 20:20:40 +00006340#ifdef USE_LONG_FNAME
6341 && USE_LONG_FNAME
6342#endif
6343 )
6344 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006345 STRMOVE(e + 1, e);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006346 *e = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006347 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006348
6349 /*
6350 * Check that, after appending the extension, the file name is really
6351 * different.
6352 */
6353 if (fname != NULL && STRCMP(fname, retval) == 0)
6354 {
6355 /* we search for a character that can be replaced by '_' */
6356 while (--s >= ptr)
6357 {
6358 if (*s != '_')
6359 {
6360 *s = '_';
6361 break;
6362 }
6363 }
6364 if (s < ptr) /* fname was "________.<ext>", how tricky! */
6365 *ptr = 'v';
6366 }
6367 return retval;
6368}
6369
6370/*
6371 * Like fgets(), but if the file line is too long, it is truncated and the
6372 * rest of the line is thrown away. Returns TRUE for end-of-file.
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01006373 * If the line is truncated then buf[size - 2] will not be NUL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006374 */
6375 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006376vim_fgets(char_u *buf, int size, FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006377{
6378 char *eof;
6379#define FGETS_SIZE 200
6380 char tbuf[FGETS_SIZE];
6381
6382 buf[size - 2] = NUL;
6383#ifdef USE_CR
6384 eof = fgets_cr((char *)buf, size, fp);
6385#else
6386 eof = fgets((char *)buf, size, fp);
6387#endif
6388 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
6389 {
6390 buf[size - 1] = NUL; /* Truncate the line */
6391
6392 /* Now throw away the rest of the line: */
6393 do
6394 {
6395 tbuf[FGETS_SIZE - 2] = NUL;
6396#ifdef USE_CR
Bram Moolenaar42335f52018-09-13 15:33:43 +02006397 vim_ignoredp = fgets_cr((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006398#else
Bram Moolenaar42335f52018-09-13 15:33:43 +02006399 vim_ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006400#endif
6401 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
6402 }
6403 return (eof == NULL);
6404}
6405
6406#if defined(USE_CR) || defined(PROTO)
6407/*
6408 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
6409 * Returns TRUE for end-of-file.
6410 * Only used for the Mac, because it's much slower than vim_fgets().
6411 */
6412 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006413tag_fgets(char_u *buf, int size, FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006414{
6415 int i = 0;
6416 int c;
6417 int eof = FALSE;
6418
6419 for (;;)
6420 {
6421 c = fgetc(fp);
6422 if (c == EOF)
6423 {
6424 eof = TRUE;
6425 break;
6426 }
6427 if (c == '\r')
6428 {
6429 /* Always store a NL for end-of-line. */
6430 if (i < size - 1)
6431 buf[i++] = '\n';
6432 c = fgetc(fp);
6433 if (c != '\n') /* Macintosh format: single CR. */
6434 ungetc(c, fp);
6435 break;
6436 }
6437 if (i < size - 1)
6438 buf[i++] = c;
6439 if (c == '\n')
6440 break;
6441 }
6442 buf[i] = NUL;
6443 return eof;
6444}
6445#endif
6446
6447/*
6448 * rename() only works if both files are on the same file system, this
6449 * function will (attempts to?) copy the file across if rename fails -- webb
6450 * Return -1 for failure, 0 for success.
6451 */
6452 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006453vim_rename(char_u *from, char_u *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006454{
6455 int fd_in;
6456 int fd_out;
6457 int n;
6458 char *errmsg = NULL;
6459 char *buffer;
6460#ifdef AMIGA
6461 BPTR flock;
6462#endif
Bram Moolenaar8767f522016-07-01 17:17:39 +02006463 stat_T st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006464 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006465#ifdef HAVE_ACL
6466 vim_acl_T acl; /* ACL from original file */
6467#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006468 int use_tmp_file = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006469
6470 /*
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006471 * When the names are identical, there is nothing to do. When they refer
6472 * to the same file (ignoring case and slash/backslash differences) but
6473 * the file name differs we need to go through a temp file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006474 */
6475 if (fnamecmp(from, to) == 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006476 {
Bram Moolenaar71afbfe2013-03-19 16:49:16 +01006477 if (p_fic && STRCMP(gettail(from), gettail(to)) != 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006478 use_tmp_file = TRUE;
6479 else
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006480 return 0;
6481 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006482
6483 /*
6484 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
6485 */
6486 if (mch_stat((char *)from, &st) < 0)
6487 return -1;
6488
Bram Moolenaar3576da72008-12-30 15:15:57 +00006489#ifdef UNIX
6490 {
Bram Moolenaar8767f522016-07-01 17:17:39 +02006491 stat_T st_to;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006492
6493 /* It's possible for the source and destination to be the same file.
6494 * This happens when "from" and "to" differ in case and are on a FAT32
6495 * filesystem. In that case go through a temp file name. */
6496 if (mch_stat((char *)to, &st_to) >= 0
6497 && st.st_dev == st_to.st_dev
6498 && st.st_ino == st_to.st_ino)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006499 use_tmp_file = TRUE;
6500 }
6501#endif
Bram Moolenaar1c32dff2011-05-05 16:41:24 +02006502#ifdef WIN3264
6503 {
6504 BY_HANDLE_FILE_INFORMATION info1, info2;
6505
6506 /* It's possible for the source and destination to be the same file.
6507 * In that case go through a temp file name. This makes rename("foo",
6508 * "./foo") a no-op (in a complicated way). */
6509 if (win32_fileinfo(from, &info1) == FILEINFO_OK
6510 && win32_fileinfo(to, &info2) == FILEINFO_OK
6511 && info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
6512 && info1.nFileIndexHigh == info2.nFileIndexHigh
6513 && info1.nFileIndexLow == info2.nFileIndexLow)
6514 use_tmp_file = TRUE;
6515 }
6516#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006517
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006518 if (use_tmp_file)
6519 {
6520 char tempname[MAXPATHL + 1];
6521
6522 /*
6523 * Find a name that doesn't exist and is in the same directory.
6524 * Rename "from" to "tempname" and then rename "tempname" to "to".
6525 */
6526 if (STRLEN(from) >= MAXPATHL - 5)
6527 return -1;
6528 STRCPY(tempname, from);
6529 for (n = 123; n < 99999; ++n)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006530 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006531 sprintf((char *)gettail((char_u *)tempname), "%d", n);
6532 if (mch_stat(tempname, &st) < 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006533 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006534 if (mch_rename((char *)from, tempname) == 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006535 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006536 if (mch_rename(tempname, (char *)to) == 0)
6537 return 0;
6538 /* Strange, the second step failed. Try moving the
6539 * file back and return failure. */
6540 mch_rename(tempname, (char *)from);
Bram Moolenaar3576da72008-12-30 15:15:57 +00006541 return -1;
6542 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006543 /* If it fails for one temp name it will most likely fail
6544 * for any temp name, give up. */
6545 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006546 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006547 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006548 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006549 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006550
Bram Moolenaar071d4272004-06-13 20:20:40 +00006551 /*
6552 * Delete the "to" file, this is required on some systems to make the
6553 * mch_rename() work, on other systems it makes sure that we don't have
6554 * two files when the mch_rename() fails.
6555 */
6556
6557#ifdef AMIGA
6558 /*
6559 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
6560 * that the name of the "to" file is the same as the "from" file, even
Bram Moolenaar7263a772007-05-10 17:35:54 +00006561 * though the names are different. To avoid the chance of accidentally
Bram Moolenaar071d4272004-06-13 20:20:40 +00006562 * deleting the "from" file (horror!) we lock it during the remove.
6563 *
6564 * When used for making a backup before writing the file: This should not
6565 * happen with ":w", because startscript() should detect this problem and
6566 * set buf->b_shortname, causing modname() to return a correct ".bak" file
6567 * name. This problem does exist with ":w filename", but then the
6568 * original file will be somewhere else so the backup isn't really
6569 * important. If autoscripting is off the rename may fail.
6570 */
6571 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
6572#endif
6573 mch_remove(to);
6574#ifdef AMIGA
6575 if (flock)
6576 UnLock(flock);
6577#endif
6578
6579 /*
6580 * First try a normal rename, return if it works.
6581 */
6582 if (mch_rename((char *)from, (char *)to) == 0)
6583 return 0;
6584
6585 /*
6586 * Rename() failed, try copying the file.
6587 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006588 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006589#ifdef HAVE_ACL
6590 /* For systems that support ACL: get the ACL from the original file. */
6591 acl = mch_get_acl(from);
6592#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006593 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
6594 if (fd_in == -1)
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006595 {
6596#ifdef HAVE_ACL
6597 mch_free_acl(acl);
6598#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006599 return -1;
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006600 }
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006601
6602 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00006603 fd_out = mch_open((char *)to,
6604 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006605 if (fd_out == -1)
6606 {
6607 close(fd_in);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006608#ifdef HAVE_ACL
6609 mch_free_acl(acl);
6610#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006611 return -1;
6612 }
6613
6614 buffer = (char *)alloc(BUFSIZE);
6615 if (buffer == NULL)
6616 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006617 close(fd_out);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006618 close(fd_in);
6619#ifdef HAVE_ACL
6620 mch_free_acl(acl);
6621#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006622 return -1;
6623 }
6624
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01006625 while ((n = read_eintr(fd_in, buffer, BUFSIZE)) > 0)
6626 if (write_eintr(fd_out, buffer, n) != n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006627 {
6628 errmsg = _("E208: Error writing to \"%s\"");
6629 break;
6630 }
6631
6632 vim_free(buffer);
6633 close(fd_in);
6634 if (close(fd_out) < 0)
6635 errmsg = _("E209: Error closing \"%s\"");
6636 if (n < 0)
6637 {
6638 errmsg = _("E210: Error reading \"%s\"");
6639 to = from;
6640 }
Bram Moolenaar7263a772007-05-10 17:35:54 +00006641#ifndef UNIX /* for Unix mch_open() already set the permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006642 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00006643#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006644#ifdef HAVE_ACL
6645 mch_set_acl(to, acl);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006646 mch_free_acl(acl);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006647#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02006648#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaare8747442013-11-12 18:09:29 +01006649 mch_copy_sec(from, to);
Bram Moolenaar0671de32013-11-12 05:12:03 +01006650#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006651 if (errmsg != NULL)
6652 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006653 semsg(errmsg, to);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006654 return -1;
6655 }
6656 mch_remove(from);
6657 return 0;
6658}
6659
6660static int already_warned = FALSE;
6661
6662/*
6663 * Check if any not hidden buffer has been changed.
6664 * Postpone the check if there are characters in the stuff buffer, a global
6665 * command is being executed, a mapping is being executed or an autocommand is
6666 * busy.
6667 * Returns TRUE if some message was written (screen should be redrawn and
6668 * cursor positioned).
6669 */
6670 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006671check_timestamps(
6672 int focus) /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006673{
6674 buf_T *buf;
6675 int didit = 0;
6676 int n;
6677
6678 /* Don't check timestamps while system() or another low-level function may
6679 * cause us to lose and gain focus. */
6680 if (no_check_timestamps > 0)
6681 return FALSE;
6682
6683 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6684 * event and we would keep on checking if the file is steadily growing.
6685 * Do check again after typing something. */
6686 if (focus && did_check_timestamps)
6687 {
6688 need_check_timestamps = TRUE;
6689 return FALSE;
6690 }
6691
6692 if (!stuff_empty() || global_busy || !typebuf_typed()
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006693 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006694 need_check_timestamps = TRUE; /* check later */
6695 else
6696 {
6697 ++no_wait_return;
6698 did_check_timestamps = TRUE;
6699 already_warned = FALSE;
Bram Moolenaar29323592016-07-24 22:04:11 +02006700 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006701 {
6702 /* Only check buffers in a window. */
6703 if (buf->b_nwindows > 0)
6704 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006705 bufref_T bufref;
6706
6707 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006708 n = buf_check_timestamp(buf, focus);
6709 if (didit < n)
6710 didit = n;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006711 if (n > 0 && !bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006712 {
6713 /* Autocommands have removed the buffer, start at the
6714 * first one again. */
6715 buf = firstbuf;
6716 continue;
6717 }
6718 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006719 }
6720 --no_wait_return;
6721 need_check_timestamps = FALSE;
6722 if (need_wait_return && didit == 2)
6723 {
6724 /* make sure msg isn't overwritten */
Bram Moolenaar32526b32019-01-19 17:43:09 +01006725 msg_puts("\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006726 out_flush();
6727 }
6728 }
6729 return didit;
6730}
6731
6732/*
6733 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6734 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6735 * empty.
6736 */
6737 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006738move_lines(buf_T *frombuf, buf_T *tobuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006739{
6740 buf_T *tbuf = curbuf;
6741 int retval = OK;
6742 linenr_T lnum;
6743 char_u *p;
6744
6745 /* Copy the lines in "frombuf" to "tobuf". */
6746 curbuf = tobuf;
6747 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6748 {
6749 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6750 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6751 {
6752 vim_free(p);
6753 retval = FAIL;
6754 break;
6755 }
6756 vim_free(p);
6757 }
6758
6759 /* Delete all the lines in "frombuf". */
6760 if (retval != FAIL)
6761 {
6762 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006763 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6764 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006765 {
6766 /* Oops! We could try putting back the saved lines, but that
6767 * might fail again... */
6768 retval = FAIL;
6769 break;
6770 }
6771 }
6772
6773 curbuf = tbuf;
6774 return retval;
6775}
6776
6777/*
6778 * Check if buffer "buf" has been changed.
6779 * Also check if the file for a new buffer unexpectedly appeared.
6780 * return 1 if a changed buffer was found.
6781 * return 2 if a message has been displayed.
6782 * return 0 otherwise.
6783 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006784 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006785buf_check_timestamp(
6786 buf_T *buf,
6787 int focus UNUSED) /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788{
Bram Moolenaar8767f522016-07-01 17:17:39 +02006789 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006790 int stat_res;
6791 int retval = 0;
6792 char_u *path;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006793 char *tbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006794 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006795 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006796 int helpmesg = FALSE;
6797 int reload = FALSE;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006798 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006799#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6800 int can_reload = FALSE;
6801#endif
Bram Moolenaar8767f522016-07-01 17:17:39 +02006802 off_T orig_size = buf->b_orig_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006803 int orig_mode = buf->b_orig_mode;
6804#ifdef FEAT_GUI
6805 int save_mouse_correct = need_mouse_correct;
6806#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006807 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006808 int n;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006809#ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006810 char_u *s;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006811#endif
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006812 bufref_T bufref;
6813
6814 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006815
6816 /* If there is no file name, the buffer is not loaded, 'buftype' is
6817 * set, we are in the middle of a save or being called recursively: ignore
6818 * this buffer. */
6819 if (buf->b_ffname == NULL
6820 || buf->b_ml.ml_mfp == NULL
Bram Moolenaar91335e52018-08-01 17:53:12 +02006821 || !bt_normal(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006822 || buf->b_saving
Bram Moolenaar071d4272004-06-13 20:20:40 +00006823 || busy
Bram Moolenaar009b2592004-10-24 19:18:58 +00006824#ifdef FEAT_NETBEANS_INTG
6825 || isNetbeansBuffer(buf)
6826#endif
Bram Moolenaar8cad9302017-08-12 14:32:32 +02006827#ifdef FEAT_TERMINAL
6828 || buf->b_term != NULL
6829#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006830 )
6831 return 0;
6832
6833 if ( !(buf->b_flags & BF_NOTEDITED)
6834 && buf->b_mtime != 0
6835 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6836 || time_differs((long)st.st_mtime, buf->b_mtime)
Bram Moolenaara7611f62014-05-02 15:46:14 +02006837 || st.st_size != buf->b_orig_size
Bram Moolenaar071d4272004-06-13 20:20:40 +00006838#ifdef HAVE_ST_MODE
6839 || (int)st.st_mode != buf->b_orig_mode
6840#else
6841 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6842#endif
6843 ))
6844 {
6845 retval = 1;
6846
Bram Moolenaar386bc822018-07-07 18:34:12 +02006847 // set b_mtime to stop further warnings (e.g., when executing
6848 // FileChangedShell autocmd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006849 if (stat_res < 0)
6850 {
Bram Moolenaar386bc822018-07-07 18:34:12 +02006851 // When 'autoread' is set we'll check the file again to see if it
6852 // re-appears.
6853 buf->b_mtime = buf->b_p_ar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006854 buf->b_orig_size = 0;
6855 buf->b_orig_mode = 0;
6856 }
6857 else
6858 buf_store_time(buf, &st, buf->b_ffname);
6859
6860 /* Don't do anything for a directory. Might contain the file
6861 * explorer. */
6862 if (mch_isdir(buf->b_fname))
6863 ;
6864
6865 /*
6866 * If 'autoread' is set, the buffer has no changes and the file still
6867 * exists, reload the buffer. Use the buffer-local option value if it
6868 * was set, the global option value otherwise.
6869 */
6870 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6871 && !bufIsChanged(buf) && stat_res >= 0)
6872 reload = TRUE;
6873 else
6874 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006875 if (stat_res < 0)
6876 reason = "deleted";
6877 else if (bufIsChanged(buf))
6878 reason = "conflict";
6879 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6880 reason = "changed";
6881 else if (orig_mode != buf->b_orig_mode)
6882 reason = "mode";
6883 else
6884 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006885
6886 /*
6887 * Only give the warning if there are no FileChangedShell
6888 * autocommands.
6889 * Avoid being called recursively by setting "busy".
6890 */
6891 busy = TRUE;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006892#ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006893 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6894 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006895#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006896 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006897 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6898 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006899 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006900 busy = FALSE;
6901 if (n)
6902 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006903 if (!bufref_valid(&bufref))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006904 emsg(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006905#ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006906 s = get_vim_var_str(VV_FCS_CHOICE);
6907 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6908 reload = TRUE;
6909 else if (STRCMP(s, "ask") == 0)
6910 n = FALSE;
6911 else
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006912#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006913 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006914 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006915 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006916 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006917 if (*reason == 'd')
6918 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006919 else
6920 {
6921 helpmesg = TRUE;
6922#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6923 can_reload = TRUE;
6924#endif
6925 /*
6926 * Check if the file contents really changed to avoid
6927 * giving a warning when only the timestamp was set (e.g.,
6928 * checked out of CVS). Always warn when the buffer was
6929 * changed.
6930 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006931 if (reason[2] == 'n')
6932 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006933 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006934 mesg2 = _("See \":help W12\" for more info.");
6935 }
6936 else if (reason[1] == 'h')
6937 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006938 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006939 mesg2 = _("See \":help W11\" for more info.");
6940 }
6941 else if (*reason == 'm')
6942 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006943 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006944 mesg2 = _("See \":help W16\" for more info.");
6945 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00006946 else
6947 /* Only timestamp changed, store it to avoid a warning
6948 * in check_mtime() later. */
6949 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006950 }
6951 }
6952 }
6953
6954 }
6955 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6956 && vim_fexists(buf->b_ffname))
6957 {
6958 retval = 1;
6959 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6960 buf->b_flags |= BF_NEW_W;
6961#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6962 can_reload = TRUE;
6963#endif
6964 }
6965
6966 if (mesg != NULL)
6967 {
6968 path = home_replace_save(buf, buf->b_fname);
6969 if (path != NULL)
6970 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006971 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006972 mesg2 = "";
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006973 tbuf = (char *)alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006974 + STRLEN(mesg2) + 2));
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006975 sprintf(tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00006976#ifdef FEAT_EVAL
6977 /* Set warningmsg here, before the unimportant and output-specific
6978 * mesg2 has been appended. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006979 set_vim_var_string(VV_WARNINGMSG, (char_u *)tbuf, -1);
Bram Moolenaar496c5262009-03-18 14:42:00 +00006980#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006981#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6982 if (can_reload)
6983 {
6984 if (*mesg2 != NUL)
6985 {
6986 STRCAT(tbuf, "\n");
6987 STRCAT(tbuf, mesg2);
6988 }
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006989 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"),
6990 (char_u *)tbuf,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01006991 (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006992 reload = TRUE;
6993 }
6994 else
6995#endif
6996 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6997 {
6998 if (*mesg2 != NUL)
6999 {
7000 STRCAT(tbuf, "; ");
7001 STRCAT(tbuf, mesg2);
7002 }
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007003 emsg(tbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007004 retval = 2;
7005 }
7006 else
7007 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007008 if (!autocmd_busy)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007009 {
7010 msg_start();
Bram Moolenaar32526b32019-01-19 17:43:09 +01007011 msg_puts_attr(tbuf, HL_ATTR(HLF_E) + MSG_HIST);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007012 if (*mesg2 != NUL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01007013 msg_puts_attr(mesg2, HL_ATTR(HLF_W) + MSG_HIST);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014 msg_clr_eos();
7015 (void)msg_end();
7016 if (emsg_silent == 0)
7017 {
7018 out_flush();
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01007019#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00007020 if (!focus)
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01007021#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007022 /* give the user some time to think about it */
7023 ui_delay(1000L, TRUE);
7024
7025 /* don't redraw and erase the message */
7026 redraw_cmdline = FALSE;
7027 }
7028 }
7029 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007030 }
7031
7032 vim_free(path);
7033 vim_free(tbuf);
7034 }
7035 }
7036
7037 if (reload)
Bram Moolenaar465748e2012-08-29 18:50:54 +02007038 {
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007039 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00007040 buf_reload(buf, orig_mode);
Bram Moolenaar465748e2012-08-29 18:50:54 +02007041#ifdef FEAT_PERSISTENT_UNDO
7042 if (buf->b_p_udf && buf->b_ffname != NULL)
7043 {
7044 char_u hash[UNDO_HASH_SIZE];
7045 buf_T *save_curbuf = curbuf;
7046
7047 /* Any existing undo file is unusable, write it now. */
7048 curbuf = buf;
7049 u_compute_hash(hash);
7050 u_write_undo(NULL, FALSE, buf, hash);
7051 curbuf = save_curbuf;
7052 }
7053#endif
7054 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007055
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00007056 /* Trigger FileChangedShell when the file was changed in any way. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007057 if (bufref_valid(&bufref) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00007058 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
7059 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007060#ifdef FEAT_GUI
7061 /* restore this in case an autocommand has set it; it would break
7062 * 'mousefocus' */
7063 need_mouse_correct = save_mouse_correct;
7064#endif
7065
7066 return retval;
7067}
7068
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007069/*
7070 * Reload a buffer that is already loaded.
7071 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00007072 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
7073 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007074 */
7075 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007076buf_reload(buf_T *buf, int orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007077{
7078 exarg_T ea;
7079 pos_T old_cursor;
7080 linenr_T old_topline;
7081 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007082 buf_T *savebuf;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007083 bufref_T bufref;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007084 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007085 aco_save_T aco;
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007086 int flags = READ_NEW;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007087
7088 /* set curwin/curbuf for "buf" and save some things */
7089 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007090
7091 /* We only want to read the text from the file, not reset the syntax
7092 * highlighting, clear marks, diff status, etc. Force the fileformat
7093 * and encoding to be the same. */
7094 if (prep_exarg(&ea, buf) == OK)
7095 {
7096 old_cursor = curwin->w_cursor;
7097 old_topline = curwin->w_topline;
7098
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007099 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007100 {
7101 /* Save all the text, so that the reload can be undone.
7102 * Sync first so that this is a separate undo-able action. */
7103 u_sync(FALSE);
7104 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
7105 flags |= READ_KEEP_UNDO;
7106 }
7107
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007108 /*
7109 * To behave like when a new file is edited (matters for
7110 * BufReadPost autocommands) we first need to delete the current
7111 * buffer contents. But if reading the file fails we should keep
7112 * the old contents. Can't use memory only, the file might be
7113 * too big. Use a hidden buffer to move the buffer contents to.
7114 */
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01007115 if (BUFEMPTY() || saved == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007116 savebuf = NULL;
7117 else
7118 {
7119 /* Allocate a buffer without putting it in the buffer list. */
7120 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007121 set_bufref(&bufref, savebuf);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007122 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007123 {
7124 /* Open the memline. */
7125 curbuf = savebuf;
7126 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00007127 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007128 curbuf = buf;
7129 curwin->w_buffer = buf;
7130 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00007131 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007132 || move_lines(buf, savebuf) == FAIL)
7133 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007134 semsg(_("E462: Could not prepare for reloading \"%s\""),
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007135 buf->b_fname);
7136 saved = FAIL;
7137 }
7138 }
7139
7140 if (saved == OK)
7141 {
7142 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007143 keep_filetype = TRUE; /* don't detect 'filetype' */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007144 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
7145 (linenr_T)0,
Bram Moolenaare13b9af2017-01-13 22:01:02 +01007146 (linenr_T)MAXLNUM, &ea, flags) != OK)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007147 {
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01007148#if defined(FEAT_EVAL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007149 if (!aborting())
7150#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007151 semsg(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007152 if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007153 {
7154 /* Put the text back from the save buffer. First
7155 * delete any lines that readfile() added. */
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01007156 while (!BUFEMPTY())
Bram Moolenaar8424a622006-04-19 21:23:36 +00007157 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007158 break;
7159 (void)move_lines(savebuf, buf);
7160 }
7161 }
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007162 else if (buf == curbuf) /* "buf" still valid */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007163 {
7164 /* Mark the buffer as unmodified and free undo info. */
7165 unchanged(buf, TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007166 if ((flags & READ_KEEP_UNDO) == 0)
7167 {
7168 u_blockfree(buf);
7169 u_clearall(buf);
7170 }
7171 else
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007172 {
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007173 /* Mark all undo states as changed. */
7174 u_unchanged(curbuf);
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007175 }
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007176 }
7177 }
7178 vim_free(ea.cmd);
7179
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007180 if (savebuf != NULL && bufref_valid(&bufref))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007181 wipe_buffer(savebuf, FALSE);
7182
7183#ifdef FEAT_DIFF
7184 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00007185 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007186#endif
7187
7188 /* Restore the topline and cursor position and check it (lines may
7189 * have been removed). */
7190 if (old_topline > curbuf->b_ml.ml_line_count)
7191 curwin->w_topline = curbuf->b_ml.ml_line_count;
7192 else
7193 curwin->w_topline = old_topline;
7194 curwin->w_cursor = old_cursor;
7195 check_cursor();
7196 update_topline();
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007197 keep_filetype = FALSE;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007198#ifdef FEAT_FOLDING
7199 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007200 win_T *wp;
7201 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007202
7203 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007204 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007205 if (wp->w_buffer == curwin->w_buffer
7206 && !foldmethodIsManual(wp))
7207 foldUpdateAll(wp);
7208 }
7209#endif
7210 /* If the mode didn't change and 'readonly' was set, keep the old
7211 * value; the user probably used the ":view" command. But don't
7212 * reset it, might have had a read error. */
7213 if (orig_mode == curbuf->b_orig_mode)
7214 curbuf->b_p_ro |= old_ro;
Bram Moolenaar52f85b72013-01-30 14:13:56 +01007215
7216 /* Modelines must override settings done by autocommands. */
7217 do_modelines(0);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007218 }
7219
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007220 /* restore curwin/curbuf and a few other things */
7221 aucmd_restbuf(&aco);
7222 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007223}
7224
Bram Moolenaar071d4272004-06-13 20:20:40 +00007225 void
Bram Moolenaar8767f522016-07-01 17:17:39 +02007226buf_store_time(buf_T *buf, stat_T *st, char_u *fname UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007227{
7228 buf->b_mtime = (long)st->st_mtime;
Bram Moolenaar914703b2010-05-31 21:59:46 +02007229 buf->b_orig_size = st->st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007230#ifdef HAVE_ST_MODE
7231 buf->b_orig_mode = (int)st->st_mode;
7232#else
7233 buf->b_orig_mode = mch_getperm(fname);
7234#endif
7235}
7236
7237/*
7238 * Adjust the line with missing eol, used for the next write.
7239 * Used for do_filter(), when the input lines for the filter are deleted.
7240 */
7241 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007242write_lnum_adjust(linenr_T offset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007243{
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01007244 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
7245 curbuf->b_no_eol_lnum += offset;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007246}
7247
Bram Moolenaarda440d22016-01-16 21:27:23 +01007248#if defined(TEMPDIRNAMES) || defined(FEAT_EVAL) || defined(PROTO)
7249/*
7250 * Delete "name" and everything in it, recursively.
7251 * return 0 for succes, -1 if some file was not deleted.
7252 */
7253 int
7254delete_recursive(char_u *name)
7255{
7256 int result = 0;
7257 char_u **files;
7258 int file_count;
7259 int i;
7260 char_u *exp;
7261
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007262 /* A symbolic link to a directory itself is deleted, not the directory it
7263 * points to. */
7264 if (
Bram Moolenaar203258c2016-01-17 22:15:16 +01007265# if defined(UNIX) || defined(WIN32)
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007266 mch_isrealdir(name)
Bram Moolenaar203258c2016-01-17 22:15:16 +01007267# else
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007268 mch_isdir(name)
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007269# endif
7270 )
Bram Moolenaarda440d22016-01-16 21:27:23 +01007271 {
7272 vim_snprintf((char *)NameBuff, MAXPATHL, "%s/*", name);
7273 exp = vim_strsave(NameBuff);
7274 if (exp == NULL)
7275 return -1;
7276 if (gen_expand_wildcards(1, &exp, &file_count, &files,
Bram Moolenaar336bd622016-01-17 18:23:58 +01007277 EW_DIR|EW_FILE|EW_SILENT|EW_ALLLINKS|EW_DODOT|EW_EMPTYOK) == OK)
Bram Moolenaarda440d22016-01-16 21:27:23 +01007278 {
7279 for (i = 0; i < file_count; ++i)
7280 if (delete_recursive(files[i]) != 0)
7281 result = -1;
7282 FreeWild(file_count, files);
7283 }
7284 else
7285 result = -1;
7286 vim_free(exp);
7287 (void)mch_rmdir(name);
7288 }
7289 else
7290 result = mch_remove(name) == 0 ? 0 : -1;
7291
7292 return result;
7293}
7294#endif
7295
Bram Moolenaar071d4272004-06-13 20:20:40 +00007296#if defined(TEMPDIRNAMES) || defined(PROTO)
7297static long temp_count = 0; /* Temp filename counter. */
7298
7299/*
7300 * Delete the temp directory and all files it contains.
7301 */
7302 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007303vim_deltempdir(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007304{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007305 if (vim_tempdir != NULL)
7306 {
Bram Moolenaarda440d22016-01-16 21:27:23 +01007307 /* remove the trailing path separator */
7308 gettail(vim_tempdir)[-1] = NUL;
7309 delete_recursive(vim_tempdir);
Bram Moolenaard23a8232018-02-10 18:45:26 +01007310 VIM_CLEAR(vim_tempdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007311 }
7312}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007313
7314/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007315 * Directory "tempdir" was created. Expand this name to a full path and put
7316 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7317 * "tempdir" must be no longer than MAXPATHL.
7318 */
7319 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007320vim_settempdir(char_u *tempdir)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007321{
7322 char_u *buf;
7323
7324 buf = alloc((unsigned)MAXPATHL + 2);
7325 if (buf != NULL)
7326 {
7327 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7328 STRCPY(buf, tempdir);
Bram Moolenaara06ecab2016-07-16 14:47:36 +02007329 add_pathsep(buf);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007330 vim_tempdir = vim_strsave(buf);
7331 vim_free(buf);
7332 }
7333}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007334#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007335
7336/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007337 * vim_tempname(): Return a unique name that can be used for a temp file.
7338 *
Bram Moolenaar76ae22f2016-06-13 20:00:29 +02007339 * The temp file is NOT guaranteed to be created. If "keep" is FALSE it is
7340 * guaranteed to NOT be created.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007341 *
7342 * The returned pointer is to allocated memory.
7343 * The returned pointer is NULL if no valid name was found.
7344 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007345 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007346vim_tempname(
7347 int extra_char UNUSED, /* char to use in the name instead of '?' */
7348 int keep UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007349{
7350#ifdef USE_TMPNAM
7351 char_u itmp[L_tmpnam]; /* use tmpnam() */
7352#else
7353 char_u itmp[TEMPNAMELEN];
7354#endif
7355
7356#ifdef TEMPDIRNAMES
7357 static char *(tempdirs[]) = {TEMPDIRNAMES};
7358 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007359# ifndef EEXIST
Bram Moolenaar8767f522016-07-01 17:17:39 +02007360 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007361# endif
7362
7363 /*
7364 * This will create a directory for private use by this instance of Vim.
7365 * This is done once, and the same directory is used for all temp files.
7366 * This method avoids security problems because of symlink attacks et al.
7367 * It's also a bit faster, because we only need to check for an existing
7368 * file when creating the directory and not for each temp file.
7369 */
7370 if (vim_tempdir == NULL)
7371 {
7372 /*
7373 * Try the entries in TEMPDIRNAMES to create the temp directory.
7374 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007375 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007376 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007377# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007378 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007379 long nr;
7380 long off;
7381# endif
7382
Bram Moolenaare1a61992015-12-03 21:02:27 +01007383 /* Expand $TMP, leave room for "/v1100000/999999999".
7384 * Skip the directory check if the expansion fails. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007385 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
Bram Moolenaare1a61992015-12-03 21:02:27 +01007386 if (itmp[0] != '$' && mch_isdir(itmp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007387 {
Bram Moolenaare1a61992015-12-03 21:02:27 +01007388 /* directory exists */
Bram Moolenaara06ecab2016-07-16 14:47:36 +02007389 add_pathsep(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007390
Bram Moolenaareaf03392009-11-17 11:08:52 +00007391# ifdef HAVE_MKDTEMP
Bram Moolenaar35d88f42016-06-04 14:52:00 +02007392 {
7393# if defined(UNIX) || defined(VMS)
7394 /* Make sure the umask doesn't remove the executable bit.
7395 * "repl" has been reported to use "177". */
7396 mode_t umask_save = umask(077);
7397# endif
7398 /* Leave room for filename */
7399 STRCAT(itmp, "vXXXXXX");
7400 if (mkdtemp((char *)itmp) != NULL)
7401 vim_settempdir(itmp);
7402# if defined(UNIX) || defined(VMS)
7403 (void)umask(umask_save);
7404# endif
7405 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007406# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007407 /* Get an arbitrary number of up to 6 digits. When it's
7408 * unlikely that it already exists it will be faster,
7409 * otherwise it doesn't matter. The use of mkdir() avoids any
7410 * security problems because of the predictable number. */
7411 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007412 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007413
7414 /* Try up to 10000 different values until we find a name that
7415 * doesn't exist. */
7416 for (off = 0; off < 10000L; ++off)
7417 {
7418 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007419# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007420 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007421# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007422
Bram Moolenaareaf03392009-11-17 11:08:52 +00007423 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7424# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007425 /* If mkdir() does not set errno to EEXIST, check for
7426 * existing file here. There is a race condition then,
7427 * although it's fail-safe. */
7428 if (mch_stat((char *)itmp, &st) >= 0)
7429 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007430# endif
7431# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007432 /* Make sure the umask doesn't remove the executable bit.
7433 * "repl" has been reported to use "177". */
7434 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007435# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007436 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007437# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007438 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007439# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007440 if (r == 0)
7441 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007442 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007443 break;
7444 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007445# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007446 /* If the mkdir() didn't fail because the file/dir exists,
7447 * we probably can't create any dir here, try another
7448 * place. */
7449 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007450# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007451 break;
7452 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007453# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007454 if (vim_tempdir != NULL)
7455 break;
7456 }
7457 }
7458 }
7459
7460 if (vim_tempdir != NULL)
7461 {
7462 /* There is no need to check if the file exists, because we own the
7463 * directory and nobody else creates a file in it. */
7464 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7465 return vim_strsave(itmp);
7466 }
7467
7468 return NULL;
7469
7470#else /* TEMPDIRNAMES */
7471
7472# ifdef WIN3264
7473 char szTempFile[_MAX_PATH + 1];
7474 char buf4[4];
7475 char_u *retval;
7476 char_u *p;
7477
7478 STRCPY(itmp, "");
7479 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
Bram Moolenaarb1891912011-02-09 14:47:03 +01007480 {
7481 szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */
7482 szTempFile[1] = NUL;
7483 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007484 strcpy(buf4, "VIM");
7485 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01007486 if (GetTempFileName(szTempFile, buf4, 0, (LPSTR)itmp) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007487 return NULL;
Bram Moolenaare5c421c2015-03-31 13:33:08 +02007488 if (!keep)
7489 /* GetTempFileName() will create the file, we don't want that */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01007490 (void)DeleteFile((LPSTR)itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007491
7492 /* Backslashes in a temp file name cause problems when filtering with
7493 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7494 * didn't set 'shellslash'. */
7495 retval = vim_strsave(itmp);
7496 if (*p_shcf == '-' || p_ssl)
7497 for (p = retval; *p; ++p)
7498 if (*p == '\\')
7499 *p = '/';
7500 return retval;
7501
7502# else /* WIN3264 */
7503
7504# ifdef USE_TMPNAM
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007505 char_u *p;
7506
Bram Moolenaar071d4272004-06-13 20:20:40 +00007507 /* tmpnam() will make its own name */
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007508 p = tmpnam((char *)itmp);
7509 if (p == NULL || *p == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007510 return NULL;
7511# else
7512 char_u *p;
7513
7514# ifdef VMS_TEMPNAM
7515 /* mktemp() is not working on VMS. It seems to be
7516 * a do-nothing function. Therefore we use tempnam().
7517 */
7518 sprintf((char *)itmp, "VIM%c", extra_char);
7519 p = (char_u *)tempnam("tmp:", (char *)itmp);
7520 if (p != NULL)
7521 {
Bram Moolenaar206f0112014-03-12 16:51:55 +01007522 /* VMS will use '.LIS' if we don't explicitly specify an extension,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007523 * and VIM will then be unable to find the file later */
7524 STRCPY(itmp, p);
7525 STRCAT(itmp, ".txt");
7526 free(p);
7527 }
7528 else
7529 return NULL;
7530# else
7531 STRCPY(itmp, TEMPNAME);
7532 if ((p = vim_strchr(itmp, '?')) != NULL)
7533 *p = extra_char;
7534 if (mktemp((char *)itmp) == NULL)
7535 return NULL;
7536# endif
7537# endif
7538
7539 return vim_strsave(itmp);
7540# endif /* WIN3264 */
7541#endif /* TEMPDIRNAMES */
7542}
7543
7544#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7545/*
Bram Moolenaarb4f6a462015-10-13 19:43:17 +02007546 * Convert all backslashes in fname to forward slashes in-place, unless when
7547 * it looks like a URL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007548 */
7549 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007550forward_slash(char_u *fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007551{
7552 char_u *p;
7553
Bram Moolenaarb4f6a462015-10-13 19:43:17 +02007554 if (path_with_url(fname))
7555 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007556 for (p = fname; *p != NUL; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007557 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007558 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007559 ++p;
Bram Moolenaar13505972019-01-24 15:04:48 +01007560 else if (*p == '\\')
Bram Moolenaar071d4272004-06-13 20:20:40 +00007561 *p = '/';
7562}
7563#endif
7564
7565
7566/*
7567 * Code for automatic commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007568 */
7569
Bram Moolenaar071d4272004-06-13 20:20:40 +00007570/*
7571 * The autocommands are stored in a list for each event.
7572 * Autocommands for the same pattern, that are consecutive, are joined
7573 * together, to avoid having to match the pattern too often.
7574 * The result is an array of Autopat lists, which point to AutoCmd lists:
7575 *
Bram Moolenaar462455e2017-11-10 21:53:11 +01007576 * last_autopat[0] -----------------------------+
7577 * V
Bram Moolenaar071d4272004-06-13 20:20:40 +00007578 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7579 * Autopat.cmds Autopat.cmds
7580 * | |
7581 * V V
7582 * AutoCmd.next AutoCmd.next
7583 * | |
7584 * V V
7585 * AutoCmd.next NULL
7586 * |
7587 * V
7588 * NULL
7589 *
Bram Moolenaar462455e2017-11-10 21:53:11 +01007590 * last_autopat[1] --------+
7591 * V
Bram Moolenaar071d4272004-06-13 20:20:40 +00007592 * first_autopat[1] --> Autopat.next --> NULL
7593 * Autopat.cmds
7594 * |
7595 * V
7596 * AutoCmd.next
7597 * |
7598 * V
7599 * NULL
7600 * etc.
7601 *
7602 * The order of AutoCmds is important, this is the order in which they were
7603 * defined and will have to be executed.
7604 */
7605typedef struct AutoCmd
7606{
7607 char_u *cmd; /* The command to be executed (NULL
7608 when command has been removed) */
7609 char nested; /* If autocommands nest here */
7610 char last; /* last command in list */
7611#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02007612 sctx_T script_ctx; /* script context where defined */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007613#endif
7614 struct AutoCmd *next; /* Next AutoCmd in list */
7615} AutoCmd;
7616
7617typedef struct AutoPat
7618{
Bram Moolenaar462455e2017-11-10 21:53:11 +01007619 struct AutoPat *next; /* next AutoPat in AutoPat list; MUST
7620 * be the first entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007621 char_u *pat; /* pattern as typed (NULL when pattern
7622 has been removed) */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007623 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007624 AutoCmd *cmds; /* list of commands to do */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007625 int group; /* group ID */
7626 int patlen; /* strlen() of pat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007627 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007628 char allow_dirs; /* Pattern may match whole path */
7629 char last; /* last pattern for apply_autocmds() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007630} AutoPat;
7631
7632static struct event_name
7633{
7634 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007635 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007636} event_names[] =
7637{
7638 {"BufAdd", EVENT_BUFADD},
7639 {"BufCreate", EVENT_BUFADD},
7640 {"BufDelete", EVENT_BUFDELETE},
7641 {"BufEnter", EVENT_BUFENTER},
7642 {"BufFilePost", EVENT_BUFFILEPOST},
7643 {"BufFilePre", EVENT_BUFFILEPRE},
7644 {"BufHidden", EVENT_BUFHIDDEN},
7645 {"BufLeave", EVENT_BUFLEAVE},
7646 {"BufNew", EVENT_BUFNEW},
7647 {"BufNewFile", EVENT_BUFNEWFILE},
7648 {"BufRead", EVENT_BUFREADPOST},
7649 {"BufReadCmd", EVENT_BUFREADCMD},
7650 {"BufReadPost", EVENT_BUFREADPOST},
7651 {"BufReadPre", EVENT_BUFREADPRE},
7652 {"BufUnload", EVENT_BUFUNLOAD},
7653 {"BufWinEnter", EVENT_BUFWINENTER},
7654 {"BufWinLeave", EVENT_BUFWINLEAVE},
7655 {"BufWipeout", EVENT_BUFWIPEOUT},
7656 {"BufWrite", EVENT_BUFWRITEPRE},
7657 {"BufWritePost", EVENT_BUFWRITEPOST},
7658 {"BufWritePre", EVENT_BUFWRITEPRE},
7659 {"BufWriteCmd", EVENT_BUFWRITECMD},
Bram Moolenaar153b7042018-01-31 15:48:32 +01007660 {"CmdlineChanged", EVENT_CMDLINECHANGED},
Bram Moolenaarfafcf0d2017-10-19 18:35:51 +02007661 {"CmdlineEnter", EVENT_CMDLINEENTER},
7662 {"CmdlineLeave", EVENT_CMDLINELEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007663 {"CmdwinEnter", EVENT_CMDWINENTER},
7664 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaard5005162014-08-22 23:05:54 +02007665 {"CmdUndefined", EVENT_CMDUNDEFINED},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007666 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar60a68362018-04-30 15:40:48 +02007667 {"ColorSchemePre", EVENT_COLORSCHEMEPRE},
Bram Moolenaarcfa3cae2012-07-10 17:14:56 +02007668 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007669 {"CursorHold", EVENT_CURSORHOLD},
7670 {"CursorHoldI", EVENT_CURSORHOLDI},
7671 {"CursorMoved", EVENT_CURSORMOVED},
7672 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaare8fa05b2018-09-16 15:48:06 +02007673 {"DiffUpdated", EVENT_DIFFUPDATED},
Bram Moolenaarb7407d32018-02-03 17:36:27 +01007674 {"DirChanged", EVENT_DIRCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007675 {"EncodingChanged", EVENT_ENCODINGCHANGED},
Bram Moolenaar12a96de2018-03-11 14:44:18 +01007676 {"ExitPre", EVENT_EXITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007677 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007678 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7679 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7680 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7681 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007682 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007683 {"FileChangedRO", EVENT_FILECHANGEDRO},
7684 {"FileReadPost", EVENT_FILEREADPOST},
7685 {"FileReadPre", EVENT_FILEREADPRE},
7686 {"FileReadCmd", EVENT_FILEREADCMD},
7687 {"FileType", EVENT_FILETYPE},
7688 {"FileWritePost", EVENT_FILEWRITEPOST},
7689 {"FileWritePre", EVENT_FILEWRITEPRE},
7690 {"FileWriteCmd", EVENT_FILEWRITECMD},
7691 {"FilterReadPost", EVENT_FILTERREADPOST},
7692 {"FilterReadPre", EVENT_FILTERREADPRE},
7693 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7694 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7695 {"FocusGained", EVENT_FOCUSGAINED},
7696 {"FocusLost", EVENT_FOCUSLOST},
7697 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7698 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007699 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007700 {"InsertChange", EVENT_INSERTCHANGE},
7701 {"InsertEnter", EVENT_INSERTENTER},
7702 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaare659c952011-05-19 17:25:41 +02007703 {"InsertCharPre", EVENT_INSERTCHARPRE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007704 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar53744302015-07-17 17:38:22 +02007705 {"OptionSet", EVENT_OPTIONSET},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007706 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7707 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar3b53dfb2012-06-06 18:03:07 +02007708 {"QuitPre", EVENT_QUITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007709 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007710 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007711 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7712 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007713 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaar2b618522019-01-12 13:26:03 +01007714 {"SourcePre", EVENT_SOURCEPRE},
7715 {"SourcePost", EVENT_SOURCEPOST},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007716 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007717 {"StdinReadPost", EVENT_STDINREADPOST},
7718 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007719 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007720 {"Syntax", EVENT_SYNTAX},
Bram Moolenaarc917da42016-07-19 22:31:36 +02007721 {"TabNew", EVENT_TABNEW},
Bram Moolenaar12c11d52016-07-19 23:13:03 +02007722 {"TabClosed", EVENT_TABCLOSED},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007723 {"TabEnter", EVENT_TABENTER},
7724 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007725 {"TermChanged", EVENT_TERMCHANGED},
Bram Moolenaarb852c3e2018-03-11 16:55:36 +01007726 {"TerminalOpen", EVENT_TERMINALOPEN},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007727 {"TermResponse", EVENT_TERMRESPONSE},
Bram Moolenaar186628f2013-03-19 13:33:23 +01007728 {"TextChanged", EVENT_TEXTCHANGED},
7729 {"TextChangedI", EVENT_TEXTCHANGEDI},
Bram Moolenaar5a093432018-02-10 18:15:19 +01007730 {"TextChangedP", EVENT_TEXTCHANGEDP},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007731 {"User", EVENT_USER},
7732 {"VimEnter", EVENT_VIMENTER},
7733 {"VimLeave", EVENT_VIMLEAVE},
7734 {"VimLeavePre", EVENT_VIMLEAVEPRE},
Bram Moolenaarc917da42016-07-19 22:31:36 +02007735 {"WinNew", EVENT_WINNEW},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007736 {"WinEnter", EVENT_WINENTER},
7737 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007738 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007739 {"TextYankPost", EVENT_TEXTYANKPOST},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007740 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007741};
7742
7743static AutoPat *first_autopat[NUM_EVENTS] =
7744{
7745 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7746 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7747 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7748 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007749 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaar53744302015-07-17 17:38:22 +02007750 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007751};
7752
Bram Moolenaar462455e2017-11-10 21:53:11 +01007753static AutoPat *last_autopat[NUM_EVENTS] =
7754{
7755 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7756 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7757 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7758 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7759 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7760 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
7761};
7762
Bram Moolenaar071d4272004-06-13 20:20:40 +00007763/*
7764 * struct used to keep status while executing autocommands for an event.
7765 */
7766typedef struct AutoPatCmd
7767{
7768 AutoPat *curpat; /* next AutoPat to examine */
7769 AutoCmd *nextcmd; /* next AutoCmd to execute */
7770 int group; /* group being used */
7771 char_u *fname; /* fname to match with */
7772 char_u *sfname; /* sfname to match with */
7773 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007774 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007775 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7776 buf is deleted */
7777 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007778} AutoPatCmd;
7779
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007780static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007781
Bram Moolenaar071d4272004-06-13 20:20:40 +00007782/*
7783 * augroups stores a list of autocmd group names.
7784 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007785static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007786#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
Bram Moolenaarb62cc362016-09-03 16:43:53 +02007787/* use get_deleted_augroup() to get this */
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02007788static char_u *deleted_augroup = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007789
7790/*
7791 * The ID of the current group. Group 0 is the default one.
7792 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007793static int current_augroup = AUGROUP_DEFAULT;
7794
7795static int au_need_clean = FALSE; /* need to delete marked patterns */
7796
Bram Moolenaard25c16e2016-01-29 22:13:30 +01007797static char_u *event_nr2name(event_T event);
Bram Moolenaard25c16e2016-01-29 22:13:30 +01007798static int au_get_grouparg(char_u **argp);
7799static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group);
7800static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
7801static void auto_next_pat(AutoPatCmd *apc, int stop_at_last);
Bram Moolenaard25c16e2016-01-29 22:13:30 +01007802static int match_file_pat(char_u *pattern, regprog_T **prog, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007803
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007804
Bram Moolenaar754b5602006-02-09 23:53:20 +00007805static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007806static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007807static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007808
Bram Moolenaarb62cc362016-09-03 16:43:53 +02007809 static char_u *
7810get_deleted_augroup(void)
7811{
7812 if (deleted_augroup == NULL)
7813 deleted_augroup = (char_u *)_("--Deleted--");
7814 return deleted_augroup;
7815}
7816
Bram Moolenaar071d4272004-06-13 20:20:40 +00007817/*
7818 * Show the autocommands for one AutoPat.
7819 */
7820 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007821show_autocmd(AutoPat *ap, event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007822{
7823 AutoCmd *ac;
7824
7825 /* Check for "got_int" (here and at various places below), which is set
7826 * when "q" has been hit for the "--more--" prompt */
7827 if (got_int)
7828 return;
7829 if (ap->pat == NULL) /* pattern has been removed */
7830 return;
7831
7832 msg_putchar('\n');
7833 if (got_int)
7834 return;
7835 if (event != last_event || ap->group != last_group)
7836 {
7837 if (ap->group != AUGROUP_DEFAULT)
7838 {
7839 if (AUGROUP_NAME(ap->group) == NULL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01007840 msg_puts_attr((char *)get_deleted_augroup(), HL_ATTR(HLF_E));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007841 else
Bram Moolenaar32526b32019-01-19 17:43:09 +01007842 msg_puts_attr((char *)AUGROUP_NAME(ap->group), HL_ATTR(HLF_T));
7843 msg_puts(" ");
Bram Moolenaar071d4272004-06-13 20:20:40 +00007844 }
Bram Moolenaar32526b32019-01-19 17:43:09 +01007845 msg_puts_attr((char *)event_nr2name(event), HL_ATTR(HLF_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007846 last_event = event;
7847 last_group = ap->group;
7848 msg_putchar('\n');
7849 if (got_int)
7850 return;
7851 }
7852 msg_col = 4;
7853 msg_outtrans(ap->pat);
7854
7855 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7856 {
7857 if (ac->cmd != NULL) /* skip removed commands */
7858 {
7859 if (msg_col >= 14)
7860 msg_putchar('\n');
7861 msg_col = 14;
7862 if (got_int)
7863 return;
7864 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007865#ifdef FEAT_EVAL
7866 if (p_verbose > 0)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02007867 last_set_msg(ac->script_ctx);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007868#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007869 if (got_int)
7870 return;
7871 if (ac->next != NULL)
7872 {
7873 msg_putchar('\n');
7874 if (got_int)
7875 return;
7876 }
7877 }
7878 }
7879}
7880
7881/*
7882 * Mark an autocommand pattern for deletion.
7883 */
7884 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007885au_remove_pat(AutoPat *ap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007886{
Bram Moolenaard23a8232018-02-10 18:45:26 +01007887 VIM_CLEAR(ap->pat);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007888 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007889 au_need_clean = TRUE;
7890}
7891
7892/*
7893 * Mark all commands for a pattern for deletion.
7894 */
7895 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007896au_remove_cmds(AutoPat *ap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007897{
7898 AutoCmd *ac;
7899
7900 for (ac = ap->cmds; ac != NULL; ac = ac->next)
Bram Moolenaard23a8232018-02-10 18:45:26 +01007901 VIM_CLEAR(ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007902 au_need_clean = TRUE;
7903}
7904
7905/*
7906 * Cleanup autocommands and patterns that have been deleted.
7907 * This is only done when not executing autocommands.
7908 */
7909 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007910au_cleanup(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007911{
7912 AutoPat *ap, **prev_ap;
7913 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007914 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915
7916 if (autocmd_busy || !au_need_clean)
7917 return;
7918
7919 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007920 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7921 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007922 {
7923 /* loop over all autocommand patterns */
7924 prev_ap = &(first_autopat[(int)event]);
7925 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7926 {
7927 /* loop over all commands for this pattern */
7928 prev_ac = &(ap->cmds);
7929 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7930 {
7931 /* remove the command if the pattern is to be deleted or when
7932 * the command has been marked for deletion */
7933 if (ap->pat == NULL || ac->cmd == NULL)
7934 {
7935 *prev_ac = ac->next;
7936 vim_free(ac->cmd);
7937 vim_free(ac);
7938 }
7939 else
7940 prev_ac = &(ac->next);
7941 }
7942
7943 /* remove the pattern if it has been marked for deletion */
7944 if (ap->pat == NULL)
7945 {
Bram Moolenaar462455e2017-11-10 21:53:11 +01007946 if (ap->next == NULL)
7947 {
7948 if (prev_ap == &(first_autopat[(int)event]))
7949 last_autopat[(int)event] = NULL;
7950 else
7951 /* this depends on the "next" field being the first in
7952 * the struct */
7953 last_autopat[(int)event] = (AutoPat *)prev_ap;
7954 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007955 *prev_ap = ap->next;
Bram Moolenaar473de612013-06-08 18:19:48 +02007956 vim_regfree(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007957 vim_free(ap);
7958 }
7959 else
7960 prev_ap = &(ap->next);
7961 }
7962 }
7963
7964 au_need_clean = FALSE;
7965}
7966
7967/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007968 * Called when buffer is freed, to remove/invalidate related buffer-local
7969 * autocmds.
7970 */
7971 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007972aubuflocal_remove(buf_T *buf)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007973{
7974 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007975 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007976 AutoPatCmd *apc;
7977
7978 /* invalidate currently executing autocommands */
7979 for (apc = active_apc_list; apc; apc = apc->next)
7980 if (buf->b_fnum == apc->arg_bufnr)
7981 apc->arg_bufnr = 0;
7982
7983 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007984 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7985 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007986 /* loop over all autocommand patterns */
7987 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7988 if (ap->buflocal_nr == buf->b_fnum)
7989 {
7990 au_remove_pat(ap);
7991 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007992 {
7993 verbose_enter();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007994 smsg(_("auto-removing autocommand: %s <buffer=%d>"),
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007995 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007996 verbose_leave();
7997 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007998 }
7999 au_cleanup();
8000}
8001
8002/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008003 * Add an autocmd group name.
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01008004 * Return its ID. Returns AUGROUP_ERROR (< 0) for error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008005 */
8006 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008007au_new_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008008{
8009 int i;
8010
8011 i = au_find_group(name);
8012 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
8013 {
8014 /* First try using a free entry. */
8015 for (i = 0; i < augroups.ga_len; ++i)
8016 if (AUGROUP_NAME(i) == NULL)
8017 break;
8018 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
8019 return AUGROUP_ERROR;
8020
8021 AUGROUP_NAME(i) = vim_strsave(name);
8022 if (AUGROUP_NAME(i) == NULL)
8023 return AUGROUP_ERROR;
8024 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008025 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008026 }
8027
8028 return i;
8029}
8030
8031 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008032au_del_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008033{
8034 int i;
8035
8036 i = au_find_group(name);
8037 if (i == AUGROUP_ERROR) /* the group doesn't exist */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008038 semsg(_("E367: No such group: \"%s\""), name);
Bram Moolenaarde653f02016-09-03 16:59:06 +02008039 else if (i == current_augroup)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008040 emsg(_("E936: Cannot delete the current group"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008041 else
8042 {
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008043 event_T event;
8044 AutoPat *ap;
8045 int in_use = FALSE;
8046
8047 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8048 event = (event_T)((int)event + 1))
8049 {
8050 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
Bram Moolenaar5c809082016-09-01 16:21:48 +02008051 if (ap->group == i && ap->pat != NULL)
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008052 {
8053 give_warning((char_u *)_("W19: Deleting augroup that is still in use"), TRUE);
8054 in_use = TRUE;
8055 event = NUM_EVENTS;
8056 break;
8057 }
8058 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008059 vim_free(AUGROUP_NAME(i));
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008060 if (in_use)
8061 {
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008062 AUGROUP_NAME(i) = get_deleted_augroup();
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008063 }
8064 else
8065 AUGROUP_NAME(i) = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008066 }
8067}
8068
8069/*
8070 * Find the ID of an autocmd group name.
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01008071 * Return its ID. Returns AUGROUP_ERROR (< 0) for error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008072 */
8073 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008074au_find_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008075{
8076 int i;
8077
8078 for (i = 0; i < augroups.ga_len; ++i)
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008079 if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008080 && STRCMP(AUGROUP_NAME(i), name) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008081 return i;
8082 return AUGROUP_ERROR;
8083}
8084
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008085/*
8086 * Return TRUE if augroup "name" exists.
8087 */
8088 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008089au_has_group(char_u *name)
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008090{
8091 return au_find_group(name) != AUGROUP_ERROR;
8092}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008093
Bram Moolenaar071d4272004-06-13 20:20:40 +00008094/*
8095 * ":augroup {name}".
8096 */
8097 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008098do_augroup(char_u *arg, int del_group)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008099{
8100 int i;
8101
8102 if (del_group)
8103 {
8104 if (*arg == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008105 emsg(_(e_argreq));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008106 else
8107 au_del_group(arg);
8108 }
8109 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
8110 current_augroup = AUGROUP_DEFAULT;
8111 else if (*arg) /* ":aug xxx": switch to group xxx */
8112 {
8113 i = au_new_group(arg);
8114 if (i != AUGROUP_ERROR)
8115 current_augroup = i;
8116 }
8117 else /* ":aug": list the group names */
8118 {
8119 msg_start();
8120 for (i = 0; i < augroups.ga_len; ++i)
8121 {
8122 if (AUGROUP_NAME(i) != NULL)
8123 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01008124 msg_puts((char *)AUGROUP_NAME(i));
8125 msg_puts(" ");
Bram Moolenaar071d4272004-06-13 20:20:40 +00008126 }
8127 }
8128 msg_clr_eos();
8129 msg_end();
8130 }
8131}
8132
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008133#if defined(EXITFREE) || defined(PROTO)
8134 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008135free_all_autocmds(void)
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008136{
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008137 int i;
8138 char_u *s;
8139
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008140 for (current_augroup = -1; current_augroup < augroups.ga_len;
8141 ++current_augroup)
8142 do_autocmd((char_u *)"", TRUE);
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008143
8144 for (i = 0; i < augroups.ga_len; ++i)
8145 {
8146 s = ((char_u **)(augroups.ga_data))[i];
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008147 if (s != get_deleted_augroup())
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008148 vim_free(s);
8149 }
8150 ga_clear(&augroups);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008151}
8152#endif
8153
Bram Moolenaar071d4272004-06-13 20:20:40 +00008154/*
8155 * Return the event number for event name "start".
8156 * Return NUM_EVENTS if the event name was not found.
8157 * Return a pointer to the next event name in "end".
8158 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008159 static event_T
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008160event_name2nr(char_u *start, char_u **end)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008161{
8162 char_u *p;
8163 int i;
8164 int len;
8165
Bram Moolenaare99e8442016-07-26 20:43:40 +02008166 /* the event name ends with end of line, '|', a blank or a comma */
Bram Moolenaar1c465442017-03-12 20:10:05 +01008167 for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008168 ;
8169 for (i = 0; event_names[i].name != NULL; ++i)
8170 {
8171 len = (int)STRLEN(event_names[i].name);
8172 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
8173 break;
8174 }
8175 if (*p == ',')
8176 ++p;
8177 *end = p;
8178 if (event_names[i].name == NULL)
8179 return NUM_EVENTS;
8180 return event_names[i].event;
8181}
8182
8183/*
8184 * Return the name for event "event".
8185 */
8186 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008187event_nr2name(event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008188{
8189 int i;
8190
8191 for (i = 0; event_names[i].name != NULL; ++i)
8192 if (event_names[i].event == event)
8193 return (char_u *)event_names[i].name;
8194 return (char_u *)"Unknown";
8195}
8196
8197/*
8198 * Scan over the events. "*" stands for all events.
8199 */
8200 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008201find_end_event(
8202 char_u *arg,
8203 int have_group) /* TRUE when group name was found */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008204{
8205 char_u *pat;
8206 char_u *p;
8207
8208 if (*arg == '*')
8209 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008210 if (arg[1] && !VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008211 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008212 semsg(_("E215: Illegal character after *: %s"), arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008213 return NULL;
8214 }
8215 pat = arg + 1;
8216 }
8217 else
8218 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008219 for (pat = arg; *pat && *pat != '|' && !VIM_ISWHITE(*pat); pat = p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008220 {
8221 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
8222 {
8223 if (have_group)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008224 semsg(_("E216: No such event: %s"), pat);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008225 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008226 semsg(_("E216: No such group or event: %s"), pat);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008227 return NULL;
8228 }
8229 }
8230 }
8231 return pat;
8232}
8233
8234/*
8235 * Return TRUE if "event" is included in 'eventignore'.
8236 */
8237 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008238event_ignored(event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008239{
8240 char_u *p = p_ei;
8241
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008242 while (*p != NUL)
8243 {
8244 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8245 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008246 if (event_name2nr(p, &p) == event)
8247 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008248 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008249
8250 return FALSE;
8251}
8252
8253/*
8254 * Return OK when the contents of p_ei is valid, FAIL otherwise.
8255 */
8256 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008257check_ei(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008258{
8259 char_u *p = p_ei;
8260
Bram Moolenaar071d4272004-06-13 20:20:40 +00008261 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008262 {
8263 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8264 {
8265 p += 3;
8266 if (*p == ',')
8267 ++p;
8268 }
8269 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008270 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008271 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008272
8273 return OK;
8274}
8275
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008276# if defined(FEAT_SYN_HL) || defined(PROTO)
8277
8278/*
8279 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
8280 * buffer loaded into the window. "what" must start with a comma.
8281 * Returns the old value of 'eventignore' in allocated memory.
8282 */
8283 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008284au_event_disable(char *what)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008285{
8286 char_u *new_ei;
8287 char_u *save_ei;
8288
8289 save_ei = vim_strsave(p_ei);
8290 if (save_ei != NULL)
8291 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008292 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008293 if (new_ei != NULL)
8294 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008295 if (*what == ',' && *p_ei == NUL)
8296 STRCPY(new_ei, what + 1);
8297 else
8298 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008299 set_string_option_direct((char_u *)"ei", -1, new_ei,
8300 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008301 vim_free(new_ei);
8302 }
8303 }
8304 return save_ei;
8305}
8306
8307 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008308au_event_restore(char_u *old_ei)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008309{
8310 if (old_ei != NULL)
8311 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008312 set_string_option_direct((char_u *)"ei", -1, old_ei,
8313 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008314 vim_free(old_ei);
8315 }
8316}
8317# endif /* FEAT_SYN_HL */
8318
Bram Moolenaar071d4272004-06-13 20:20:40 +00008319/*
8320 * do_autocmd() -- implements the :autocmd command. Can be used in the
8321 * following ways:
8322 *
8323 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8324 * will be automatically executed for <event>
8325 * when editing a file matching <pat>, in
8326 * the current group.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008327 * :autocmd <event> <pat> Show the autocommands associated with
Bram Moolenaar071d4272004-06-13 20:20:40 +00008328 * <event> and <pat>.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008329 * :autocmd <event> Show the autocommands associated with
Bram Moolenaar071d4272004-06-13 20:20:40 +00008330 * <event>.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008331 * :autocmd Show all autocommands.
8332 * :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
Bram Moolenaar071d4272004-06-13 20:20:40 +00008333 * <event> and <pat>, and add the command
8334 * <cmd>, for the current group.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008335 * :autocmd! <event> <pat> Remove all autocommands associated with
Bram Moolenaar071d4272004-06-13 20:20:40 +00008336 * <event> and <pat> for the current group.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008337 * :autocmd! <event> Remove all autocommands associated with
Bram Moolenaar071d4272004-06-13 20:20:40 +00008338 * <event> for the current group.
Bram Moolenaar8c555332018-06-22 21:30:31 +02008339 * :autocmd! Remove ALL autocommands for the current
Bram Moolenaar071d4272004-06-13 20:20:40 +00008340 * group.
8341 *
8342 * Multiple events and patterns may be given separated by commas. Here are
8343 * some examples:
8344 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8345 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8346 *
8347 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008348 *
8349 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008350 */
8351 void
Bram Moolenaare99e8442016-07-26 20:43:40 +02008352do_autocmd(char_u *arg_in, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008353{
Bram Moolenaare99e8442016-07-26 20:43:40 +02008354 char_u *arg = arg_in;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008355 char_u *pat;
8356 char_u *envpat = NULL;
8357 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008358 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008359 int need_free = FALSE;
8360 int nested = FALSE;
8361 int group;
8362
Bram Moolenaare99e8442016-07-26 20:43:40 +02008363 if (*arg == '|')
8364 {
8365 arg = (char_u *)"";
8366 group = AUGROUP_ALL; /* no argument, use all groups */
8367 }
8368 else
8369 {
8370 /*
8371 * Check for a legal group name. If not, use AUGROUP_ALL.
8372 */
8373 group = au_get_grouparg(&arg);
8374 if (arg == NULL) /* out of memory */
8375 return;
8376 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008377
8378 /*
8379 * Scan over the events.
8380 * If we find an illegal name, return here, don't do anything.
8381 */
8382 pat = find_end_event(arg, group != AUGROUP_ALL);
8383 if (pat == NULL)
8384 return;
8385
Bram Moolenaar071d4272004-06-13 20:20:40 +00008386 pat = skipwhite(pat);
Bram Moolenaare99e8442016-07-26 20:43:40 +02008387 if (*pat == '|')
Bram Moolenaar071d4272004-06-13 20:20:40 +00008388 {
Bram Moolenaare99e8442016-07-26 20:43:40 +02008389 pat = (char_u *)"";
8390 cmd = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +00008391 }
Bram Moolenaare99e8442016-07-26 20:43:40 +02008392 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008393 {
Bram Moolenaare99e8442016-07-26 20:43:40 +02008394 /*
8395 * Scan over the pattern. Put a NUL at the end.
8396 */
8397 cmd = pat;
Bram Moolenaar1c465442017-03-12 20:10:05 +01008398 while (*cmd && (!VIM_ISWHITE(*cmd) || cmd[-1] == '\\'))
Bram Moolenaare99e8442016-07-26 20:43:40 +02008399 cmd++;
8400 if (*cmd)
8401 *cmd++ = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008402
Bram Moolenaare99e8442016-07-26 20:43:40 +02008403 /* Expand environment variables in the pattern. Set 'shellslash', we want
8404 * forward slashes here. */
8405 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8406 {
8407#ifdef BACKSLASH_IN_FILENAME
8408 int p_ssl_save = p_ssl;
8409
8410 p_ssl = TRUE;
8411#endif
8412 envpat = expand_env_save(pat);
8413#ifdef BACKSLASH_IN_FILENAME
8414 p_ssl = p_ssl_save;
8415#endif
8416 if (envpat != NULL)
8417 pat = envpat;
8418 }
8419
8420 /*
8421 * Check for "nested" flag.
8422 */
8423 cmd = skipwhite(cmd);
Bram Moolenaar1c465442017-03-12 20:10:05 +01008424 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && VIM_ISWHITE(cmd[6]))
Bram Moolenaare99e8442016-07-26 20:43:40 +02008425 {
8426 nested = TRUE;
8427 cmd = skipwhite(cmd + 6);
8428 }
8429
8430 /*
8431 * Find the start of the commands.
8432 * Expand <sfile> in it.
8433 */
8434 if (*cmd != NUL)
8435 {
8436 cmd = expand_sfile(cmd);
8437 if (cmd == NULL) /* some error */
8438 return;
8439 need_free = TRUE;
8440 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008441 }
8442
8443 /*
8444 * Print header when showing autocommands.
8445 */
8446 if (!forceit && *cmd == NUL)
8447 {
8448 /* Highlight title */
Bram Moolenaar32526b32019-01-19 17:43:09 +01008449 msg_puts_title(_("\n--- Autocommands ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008450 }
8451
8452 /*
8453 * Loop over the events.
8454 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008455 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008456 last_group = AUGROUP_ERROR; /* for listing the group name */
Bram Moolenaare99e8442016-07-26 20:43:40 +02008457 if (*arg == '*' || *arg == NUL || *arg == '|')
Bram Moolenaar071d4272004-06-13 20:20:40 +00008458 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008459 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8460 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008461 if (do_autocmd_event(event, pat,
8462 nested, cmd, forceit, group) == FAIL)
8463 break;
8464 }
8465 else
8466 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008467 while (*arg && *arg != '|' && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008468 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8469 nested, cmd, forceit, group) == FAIL)
8470 break;
8471 }
8472
8473 if (need_free)
8474 vim_free(cmd);
8475 vim_free(envpat);
8476}
8477
8478/*
8479 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8480 * The "argp" argument is advanced to the following argument.
8481 *
8482 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8483 */
8484 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008485au_get_grouparg(char_u **argp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008486{
8487 char_u *group_name;
8488 char_u *p;
8489 char_u *arg = *argp;
8490 int group = AUGROUP_ALL;
8491
Bram Moolenaar1c465442017-03-12 20:10:05 +01008492 for (p = arg; *p && !VIM_ISWHITE(*p) && *p != '|'; ++p)
Bram Moolenaare99e8442016-07-26 20:43:40 +02008493 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008494 if (p > arg)
8495 {
8496 group_name = vim_strnsave(arg, (int)(p - arg));
8497 if (group_name == NULL) /* out of memory */
8498 return AUGROUP_ERROR;
8499 group = au_find_group(group_name);
8500 if (group == AUGROUP_ERROR)
8501 group = AUGROUP_ALL; /* no match, use all groups */
8502 else
8503 *argp = skipwhite(p); /* match, skip over group name */
8504 vim_free(group_name);
8505 }
8506 return group;
8507}
8508
8509/*
8510 * do_autocmd() for one event.
8511 * If *pat == NUL do for all patterns.
8512 * If *cmd == NUL show entries.
8513 * If forceit == TRUE delete entries.
8514 * If group is not AUGROUP_ALL, only use this group.
8515 */
8516 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008517do_autocmd_event(
8518 event_T event,
8519 char_u *pat,
8520 int nested,
8521 char_u *cmd,
8522 int forceit,
8523 int group)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008524{
8525 AutoPat *ap;
8526 AutoPat **prev_ap;
8527 AutoCmd *ac;
8528 AutoCmd **prev_ac;
8529 int brace_level;
8530 char_u *endpat;
8531 int findgroup;
8532 int allgroups;
8533 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008534 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008535 int buflocal_nr;
8536 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008537
8538 if (group == AUGROUP_ALL)
8539 findgroup = current_augroup;
8540 else
8541 findgroup = group;
8542 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8543
8544 /*
8545 * Show or delete all patterns for an event.
8546 */
8547 if (*pat == NUL)
8548 {
8549 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8550 {
8551 if (forceit) /* delete the AutoPat, if it's in the current group */
8552 {
8553 if (ap->group == findgroup)
8554 au_remove_pat(ap);
8555 }
8556 else if (group == AUGROUP_ALL || ap->group == group)
8557 show_autocmd(ap, event);
8558 }
8559 }
8560
8561 /*
8562 * Loop through all the specified patterns.
8563 */
8564 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8565 {
8566 /*
8567 * Find end of the pattern.
8568 * Watch out for a comma in braces, like "*.\{obj,o\}".
8569 */
8570 brace_level = 0;
8571 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
Bram Moolenaar6b9be1b2015-07-28 13:33:45 +02008572 || (endpat > pat && endpat[-1] == '\\')); ++endpat)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008573 {
8574 if (*endpat == '{')
8575 brace_level++;
8576 else if (*endpat == '}')
8577 brace_level--;
8578 }
8579 if (pat == endpat) /* ignore single comma */
8580 continue;
8581 patlen = (int)(endpat - pat);
8582
8583 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008584 * detect special <buflocal[=X]> buffer-local patterns
8585 */
8586 is_buflocal = FALSE;
8587 buflocal_nr = 0;
8588
Bram Moolenaar1e997822015-02-17 16:04:57 +01008589 if (patlen >= 8 && STRNCMP(pat, "<buffer", 7) == 0
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008590 && pat[patlen - 1] == '>')
8591 {
Bram Moolenaar1e997822015-02-17 16:04:57 +01008592 /* "<buffer...>": Error will be printed only for addition.
8593 * printing and removing will proceed silently. */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008594 is_buflocal = TRUE;
8595 if (patlen == 8)
Bram Moolenaar1e997822015-02-17 16:04:57 +01008596 /* "<buffer>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008597 buflocal_nr = curbuf->b_fnum;
8598 else if (patlen > 9 && pat[7] == '=')
8599 {
Bram Moolenaar1e997822015-02-17 16:04:57 +01008600 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0)
8601 /* "<buffer=abuf>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008602 buflocal_nr = autocmd_bufnr;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008603 else if (skipdigits(pat + 8) == pat + patlen - 1)
Bram Moolenaar1e997822015-02-17 16:04:57 +01008604 /* "<buffer=123>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008605 buflocal_nr = atoi((char *)pat + 8);
8606 }
8607 }
8608
8609 if (is_buflocal)
8610 {
8611 /* normalize pat into standard "<buffer>#N" form */
8612 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8613 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008614 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008615 }
8616
8617 /*
Bram Moolenaar462455e2017-11-10 21:53:11 +01008618 * Find AutoPat entries with this pattern. When adding a command it
8619 * always goes at or after the last one, so start at the end.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008620 */
Bram Moolenaar462455e2017-11-10 21:53:11 +01008621 if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL)
8622 prev_ap = &last_autopat[(int)event];
8623 else
8624 prev_ap = &first_autopat[(int)event];
Bram Moolenaar071d4272004-06-13 20:20:40 +00008625 while ((ap = *prev_ap) != NULL)
8626 {
8627 if (ap->pat != NULL)
8628 {
8629 /* Accept a pattern when:
8630 * - a group was specified and it's that group, or a group was
8631 * not specified and it's the current group, or a group was
8632 * not specified and we are listing
8633 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008634 * - the pattern matches.
8635 * For <buffer[=X]>, this condition works because we normalize
8636 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008637 */
8638 if ((allgroups || ap->group == findgroup)
8639 && ap->patlen == patlen
8640 && STRNCMP(pat, ap->pat, patlen) == 0)
8641 {
8642 /*
8643 * Remove existing autocommands.
8644 * If adding any new autocmd's for this AutoPat, don't
8645 * delete the pattern from the autopat list, append to
8646 * this list.
8647 */
8648 if (forceit)
8649 {
8650 if (*cmd != NUL && ap->next == NULL)
8651 {
8652 au_remove_cmds(ap);
8653 break;
8654 }
8655 au_remove_pat(ap);
8656 }
8657
8658 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008659 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008660 */
8661 else if (*cmd == NUL)
8662 show_autocmd(ap, event);
8663
8664 /*
8665 * Add autocmd to this autopat, if it's the last one.
8666 */
8667 else if (ap->next == NULL)
8668 break;
8669 }
8670 }
8671 prev_ap = &ap->next;
8672 }
8673
8674 /*
8675 * Add a new command.
8676 */
8677 if (*cmd != NUL)
8678 {
8679 /*
8680 * If the pattern we want to add a command to does appear at the
8681 * end of the list (or not is not in the list at all), add the
8682 * pattern at the end of the list.
8683 */
8684 if (ap == NULL)
8685 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008686 /* refuse to add buffer-local ap if buffer number is invalid */
8687 if (is_buflocal && (buflocal_nr == 0
8688 || buflist_findnr(buflocal_nr) == NULL))
8689 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008690 semsg(_("E680: <buffer=%d>: invalid buffer number "),
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008691 buflocal_nr);
8692 return FAIL;
8693 }
8694
Bram Moolenaar071d4272004-06-13 20:20:40 +00008695 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8696 if (ap == NULL)
8697 return FAIL;
8698 ap->pat = vim_strnsave(pat, patlen);
8699 ap->patlen = patlen;
8700 if (ap->pat == NULL)
8701 {
8702 vim_free(ap);
8703 return FAIL;
8704 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008705
8706 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008707 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008708 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008709 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008710 }
8711 else
8712 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008713 char_u *reg_pat;
8714
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008715 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008716 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008717 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008718 if (reg_pat != NULL)
8719 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008720 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008721 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008722 {
8723 vim_free(ap->pat);
8724 vim_free(ap);
8725 return FAIL;
8726 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008727 }
8728 ap->cmds = NULL;
8729 *prev_ap = ap;
Bram Moolenaar462455e2017-11-10 21:53:11 +01008730 last_autopat[(int)event] = ap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008731 ap->next = NULL;
8732 if (group == AUGROUP_ALL)
8733 ap->group = current_augroup;
8734 else
8735 ap->group = group;
8736 }
8737
8738 /*
8739 * Add the autocmd at the end of the AutoCmd list.
8740 */
8741 prev_ac = &(ap->cmds);
8742 while ((ac = *prev_ac) != NULL)
8743 prev_ac = &ac->next;
8744 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8745 if (ac == NULL)
8746 return FAIL;
8747 ac->cmd = vim_strsave(cmd);
8748#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02008749 ac->script_ctx = current_sctx;
8750 ac->script_ctx.sc_lnum += sourcing_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008751#endif
8752 if (ac->cmd == NULL)
8753 {
8754 vim_free(ac);
8755 return FAIL;
8756 }
8757 ac->next = NULL;
8758 *prev_ac = ac;
8759 ac->nested = nested;
8760 }
8761 }
8762
8763 au_cleanup(); /* may really delete removed patterns/commands now */
8764 return OK;
8765}
8766
8767/*
8768 * Implementation of ":doautocmd [group] event [fname]".
8769 * Return OK for success, FAIL for failure;
8770 */
8771 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008772do_doautocmd(
8773 char_u *arg,
Bram Moolenaar1610d052016-06-09 22:53:01 +02008774 int do_msg, /* give message for no matching autocmds? */
8775 int *did_something)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008776{
8777 char_u *fname;
8778 int nothing_done = TRUE;
8779 int group;
8780
Bram Moolenaar1610d052016-06-09 22:53:01 +02008781 if (did_something != NULL)
Bram Moolenaar76ae22f2016-06-13 20:00:29 +02008782 *did_something = FALSE;
Bram Moolenaar1610d052016-06-09 22:53:01 +02008783
Bram Moolenaar071d4272004-06-13 20:20:40 +00008784 /*
8785 * Check for a legal group name. If not, use AUGROUP_ALL.
8786 */
8787 group = au_get_grouparg(&arg);
8788 if (arg == NULL) /* out of memory */
8789 return FAIL;
8790
8791 if (*arg == '*')
8792 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008793 emsg(_("E217: Can't execute autocommands for ALL events"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008794 return FAIL;
8795 }
8796
8797 /*
8798 * Scan over the events.
8799 * If we find an illegal name, return here, don't do anything.
8800 */
8801 fname = find_end_event(arg, group != AUGROUP_ALL);
8802 if (fname == NULL)
8803 return FAIL;
8804
8805 fname = skipwhite(fname);
8806
8807 /*
8808 * Loop over the events.
8809 */
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02008810 while (*arg && !ends_excmd(*arg) && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008811 if (apply_autocmds_group(event_name2nr(arg, &arg),
8812 fname, NULL, TRUE, group, curbuf, NULL))
8813 nothing_done = FALSE;
8814
8815 if (nothing_done && do_msg)
Bram Moolenaar32526b32019-01-19 17:43:09 +01008816 msg(_("No matching autocommands"));
Bram Moolenaar1610d052016-06-09 22:53:01 +02008817 if (did_something != NULL)
8818 *did_something = !nothing_done;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008819
8820#ifdef FEAT_EVAL
8821 return aborting() ? FAIL : OK;
8822#else
8823 return OK;
8824#endif
8825}
8826
8827/*
8828 * ":doautoall": execute autocommands for each loaded buffer.
8829 */
8830 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008831ex_doautoall(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008832{
8833 int retval;
8834 aco_save_T aco;
8835 buf_T *buf;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008836 bufref_T bufref;
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008837 char_u *arg = eap->arg;
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008838 int call_do_modelines = check_nomodeline(&arg);
Bram Moolenaar1610d052016-06-09 22:53:01 +02008839 int did_aucmd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008840
8841 /*
8842 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8843 * equal to curbuf, but for some buffers there may not be a window.
8844 * So we change the buffer for the current window for a moment. This
8845 * gives problems when the autocommands make changes to the list of
8846 * buffers or windows...
8847 */
Bram Moolenaar29323592016-07-24 22:04:11 +02008848 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008849 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008850 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008851 {
8852 /* find a window for this buffer and save some values */
8853 aucmd_prepbuf(&aco, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008854 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008855
8856 /* execute the autocommands for this buffer */
Bram Moolenaar1610d052016-06-09 22:53:01 +02008857 retval = do_doautocmd(arg, FALSE, &did_aucmd);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008858
Bram Moolenaar1610d052016-06-09 22:53:01 +02008859 if (call_do_modelines && did_aucmd)
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008860 {
8861 /* Execute the modeline settings, but don't set window-local
8862 * options if we are using the current window for another
8863 * buffer. */
8864 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
8865 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008866
8867 /* restore the current window */
8868 aucmd_restbuf(&aco);
8869
8870 /* stop if there is some error or buffer was deleted */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008871 if (retval == FAIL || !bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008872 break;
8873 }
8874 }
8875
8876 check_cursor(); /* just in case lines got deleted */
8877}
8878
8879/*
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008880 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
8881 * return TRUE and advance *argp to after it.
8882 * Thus return TRUE when do_modelines() should be called.
8883 */
8884 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008885check_nomodeline(char_u **argp)
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008886{
8887 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
8888 {
8889 *argp = skipwhite(*argp + 12);
8890 return FALSE;
8891 }
8892 return TRUE;
8893}
8894
8895/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008896 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008897 * Search for a visible window containing the current buffer. If there isn't
8898 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008899 * Set "curbuf" and "curwin" to match "buf".
8900 */
8901 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008902aucmd_prepbuf(
8903 aco_save_T *aco, /* structure to save values in */
8904 buf_T *buf) /* new curbuf */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008905{
8906 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008907 int save_ea;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008908#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008909 int save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008910#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008911
8912 /* Find a window that is for the new buffer */
8913 if (buf == curbuf) /* be quick when buf is curbuf */
8914 win = curwin;
8915 else
Bram Moolenaar29323592016-07-24 22:04:11 +02008916 FOR_ALL_WINDOWS(win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008917 if (win->w_buffer == buf)
8918 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008919
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008920 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
8921 * back to using the current window. */
8922 if (win == NULL && aucmd_win == NULL)
8923 {
8924 win_alloc_aucmd_win();
8925 if (aucmd_win == NULL)
8926 win = curwin;
8927 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008928 if (win == NULL && aucmd_win_used)
8929 /* Strange recursive autocommand, fall back to using the current
8930 * window. Expect a few side effects... */
8931 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008932
8933 aco->save_curwin = curwin;
8934 aco->save_curbuf = curbuf;
Bram Moolenaara42df592018-12-24 00:22:39 +01008935 aco->save_prevwin = prevwin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008936 if (win != NULL)
8937 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008938 /* There is a window for "buf" in the current tab page, make it the
8939 * curwin. This is preferred, it has the least side effects (esp. if
8940 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008941 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008942 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943 }
8944 else
8945 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008946 /* There is no window for "buf", use "aucmd_win". To minimize the side
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02008947 * effects, insert it in the current tab page.
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008948 * Anything related to a window (e.g., setting folds) may have
8949 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008950 aco->use_aucmd_win = TRUE;
8951 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008952 aucmd_win->w_buffer = buf;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01008953#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
Bram Moolenaarcdddaa42010-06-07 23:07:44 +02008954 aucmd_win->w_s = &buf->b_s;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01008955#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008956 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008957 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008958
8959 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
8960 * win_enter_ext(). */
Bram Moolenaard23a8232018-02-10 18:45:26 +01008961 VIM_CLEAR(aucmd_win->w_localdir);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008962 aco->globaldir = globaldir;
8963 globaldir = NULL;
8964
Bram Moolenaar071d4272004-06-13 20:20:40 +00008965
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008966 /* Split the current window, put the aucmd_win in the upper half.
8967 * We don't want the BufEnter or WinEnter autocommands. */
8968 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008969 make_snapshot(SNAP_AUCMD_IDX);
8970 save_ea = p_ea;
8971 p_ea = FALSE;
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008972
Bram Moolenaar4033c552017-09-16 20:54:51 +02008973#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008974 /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
8975 save_acd = p_acd;
8976 p_acd = FALSE;
Bram Moolenaar4033c552017-09-16 20:54:51 +02008977#endif
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008978
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008979 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
8980 (void)win_comp_pos(); /* recompute window positions */
8981 p_ea = save_ea;
Bram Moolenaar4033c552017-09-16 20:54:51 +02008982#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008983 p_acd = save_acd;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008984#endif
Bram Moolenaar4033c552017-09-16 20:54:51 +02008985 unblock_autocmds();
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008986 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008987 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008988 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008989 aco->new_curwin = curwin;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008990 set_bufref(&aco->new_curbuf, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008991}
8992
8993/*
8994 * Cleanup after executing autocommands for a (hidden) buffer.
8995 * Restore the window as it was (if possible).
8996 */
8997 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008998aucmd_restbuf(
8999 aco_save_T *aco) /* structure holding saved values */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009000{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009001 int dummy;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009002
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009003 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009004 {
9005 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009006 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009007 * page. Do not trigger autocommands here. */
9008 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009009 if (curwin != aucmd_win)
9010 {
9011 tabpage_T *tp;
9012 win_T *wp;
9013
9014 FOR_ALL_TAB_WINDOWS(tp, wp)
9015 {
9016 if (wp == aucmd_win)
9017 {
9018 if (tp != curtab)
Bram Moolenaar49e649f2013-05-06 04:50:35 +02009019 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009020 win_goto(aucmd_win);
Bram Moolenaar28f29082012-02-11 23:45:37 +01009021 goto win_found;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009022 }
9023 }
9024 }
Bram Moolenaar28f29082012-02-11 23:45:37 +01009025win_found:
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009026
9027 /* Remove the window and frame from the tree of frames. */
9028 (void)winframe_remove(curwin, &dummy, NULL);
9029 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009030 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009031 last_status(FALSE); /* may need to remove last status line */
Bram Moolenaar8c752bd2017-03-19 17:09:56 +01009032
9033 if (!valid_tabpage_win(curtab))
9034 /* no valid window in current tabpage */
9035 close_tabpage(curtab);
9036
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009037 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
9038 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009039 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009040
9041 if (win_valid(aco->save_curwin))
9042 curwin = aco->save_curwin;
9043 else
9044 /* Hmm, original window disappeared. Just use the first one. */
9045 curwin = firstwin;
Bram Moolenaara42df592018-12-24 00:22:39 +01009046 if (win_valid(aco->save_prevwin))
9047 prevwin = aco->save_prevwin;
Bram Moolenaar4033c552017-09-16 20:54:51 +02009048#ifdef FEAT_EVAL
Bram Moolenaar429fa852013-04-15 12:27:36 +02009049 vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
9050 hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009051#endif
9052 curbuf = curwin->w_buffer;
9053
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009054 vim_free(globaldir);
9055 globaldir = aco->globaldir;
9056
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009057 /* the buffer contents may have changed */
9058 check_cursor();
9059 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
9060 {
9061 curwin->w_topline = curbuf->b_ml.ml_line_count;
9062#ifdef FEAT_DIFF
9063 curwin->w_topfill = 0;
9064#endif
9065 }
9066#if defined(FEAT_GUI)
9067 /* Hide the scrollbars from the aucmd_win and update. */
9068 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
9069 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
9070 gui_may_update_scrollbars();
9071#endif
9072 }
9073 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009074 {
9075 /* restore curwin */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009076 if (win_valid(aco->save_curwin))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009077 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009078 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009079 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009080 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009081 if (curwin == aco->new_curwin
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009082 && curbuf != aco->new_curbuf.br_buf
9083 && bufref_valid(&aco->new_curbuf)
9084 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009085 {
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009086# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
9087 if (curwin->w_s == &curbuf->b_s)
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009088 curwin->w_s = &aco->new_curbuf.br_buf->b_s;
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009089# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009090 --curbuf->b_nwindows;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009091 curbuf = aco->new_curbuf.br_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009092 curwin->w_buffer = curbuf;
9093 ++curbuf->b_nwindows;
9094 }
9095
9096 curwin = aco->save_curwin;
9097 curbuf = curwin->w_buffer;
Bram Moolenaara42df592018-12-24 00:22:39 +01009098 if (win_valid(aco->save_prevwin))
9099 prevwin = aco->save_prevwin;
Bram Moolenaar371932a2014-09-09 16:59:38 +02009100 /* In case the autocommand move the cursor to a position that that
9101 * not exist in curbuf. */
9102 check_cursor();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009103 }
9104 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009105}
9106
9107static int autocmd_nested = FALSE;
9108
9109/*
9110 * Execute autocommands for "event" and file name "fname".
9111 * Return TRUE if some commands were executed.
9112 */
9113 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009114apply_autocmds(
9115 event_T event,
9116 char_u *fname, /* NULL or empty means use actual file name */
9117 char_u *fname_io, /* fname to use for <afile> on cmdline */
9118 int force, /* when TRUE, ignore autocmd_busy */
9119 buf_T *buf) /* buffer for <abuf> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009120{
9121 return apply_autocmds_group(event, fname, fname_io, force,
9122 AUGROUP_ALL, buf, NULL);
9123}
9124
9125/*
9126 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
9127 * setting v:filearg.
9128 */
9129 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009130apply_autocmds_exarg(
9131 event_T event,
9132 char_u *fname,
9133 char_u *fname_io,
9134 int force,
9135 buf_T *buf,
9136 exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009137{
9138 return apply_autocmds_group(event, fname, fname_io, force,
9139 AUGROUP_ALL, buf, eap);
9140}
9141
9142/*
9143 * Like apply_autocmds(), but handles the caller's retval. If the script
9144 * processing is being aborted or if retval is FAIL when inside a try
9145 * conditional, no autocommands are executed. If otherwise the autocommands
9146 * cause the script to be aborted, retval is set to FAIL.
9147 */
9148 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009149apply_autocmds_retval(
9150 event_T event,
9151 char_u *fname, /* NULL or empty means use actual file name */
9152 char_u *fname_io, /* fname to use for <afile> on cmdline */
9153 int force, /* when TRUE, ignore autocmd_busy */
9154 buf_T *buf, /* buffer for <abuf> */
9155 int *retval) /* pointer to caller's retval */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009156{
9157 int did_cmd;
9158
Bram Moolenaar1e015462005-09-25 22:16:38 +00009159#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009160 if (should_abort(*retval))
9161 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00009162#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009163
9164 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
9165 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00009166 if (did_cmd
9167#ifdef FEAT_EVAL
9168 && aborting()
9169#endif
9170 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00009171 *retval = FAIL;
9172 return did_cmd;
9173}
9174
Bram Moolenaard35f9712005-12-18 22:02:33 +00009175/*
9176 * Return TRUE when there is a CursorHold autocommand defined.
9177 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009178 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009179has_cursorhold(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009180{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009181 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
9182 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009183}
Bram Moolenaard35f9712005-12-18 22:02:33 +00009184
9185/*
9186 * Return TRUE if the CursorHold event can be triggered.
9187 */
9188 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009189trigger_cursorhold(void)
Bram Moolenaard35f9712005-12-18 22:02:33 +00009190{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009191 int state;
9192
Bram Moolenaar05334432011-07-20 18:29:39 +02009193 if (!did_cursorhold
9194 && has_cursorhold()
Bram Moolenaar0b6d9112018-05-22 20:35:17 +02009195 && reg_recording == 0
Bram Moolenaar05334432011-07-20 18:29:39 +02009196 && typebuf.tb_len == 0
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00009197#ifdef FEAT_INS_EXPAND
9198 && !ins_compl_active()
9199#endif
9200 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00009201 {
9202 state = get_real_state();
9203 if (state == NORMAL_BUSY || (state & INSERT) != 0)
9204 return TRUE;
9205 }
9206 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00009207}
Bram Moolenaar754b5602006-02-09 23:53:20 +00009208
9209/*
9210 * Return TRUE when there is a CursorMoved autocommand defined.
9211 */
9212 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009213has_cursormoved(void)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009214{
9215 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
9216}
9217
Bram Moolenaar113e1072019-01-20 15:30:40 +01009218#if defined(FEAT_CONCEAL) || defined(PROTO)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009219/*
9220 * Return TRUE when there is a CursorMovedI autocommand defined.
9221 */
9222 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009223has_cursormovedI(void)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009224{
9225 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
9226}
Bram Moolenaar113e1072019-01-20 15:30:40 +01009227#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009228
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009229/*
Bram Moolenaar186628f2013-03-19 13:33:23 +01009230 * Return TRUE when there is a TextChanged autocommand defined.
9231 */
9232 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009233has_textchanged(void)
Bram Moolenaar186628f2013-03-19 13:33:23 +01009234{
9235 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
9236}
9237
9238/*
9239 * Return TRUE when there is a TextChangedI autocommand defined.
9240 */
9241 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009242has_textchangedI(void)
Bram Moolenaar186628f2013-03-19 13:33:23 +01009243{
9244 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
9245}
9246
Bram Moolenaar113e1072019-01-20 15:30:40 +01009247#if defined(FEAT_INS_EXPAND) || defined(PROTO)
Bram Moolenaar186628f2013-03-19 13:33:23 +01009248/*
Bram Moolenaar5a093432018-02-10 18:15:19 +01009249 * Return TRUE when there is a TextChangedP autocommand defined.
9250 */
9251 int
9252has_textchangedP(void)
9253{
9254 return (first_autopat[(int)EVENT_TEXTCHANGEDP] != NULL);
9255}
Bram Moolenaar113e1072019-01-20 15:30:40 +01009256#endif
Bram Moolenaar5a093432018-02-10 18:15:19 +01009257
9258/*
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009259 * Return TRUE when there is an InsertCharPre autocommand defined.
9260 */
9261 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009262has_insertcharpre(void)
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009263{
9264 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
9265}
9266
Bram Moolenaard5005162014-08-22 23:05:54 +02009267/*
9268 * Return TRUE when there is an CmdUndefined autocommand defined.
9269 */
9270 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009271has_cmdundefined(void)
Bram Moolenaard5005162014-08-22 23:05:54 +02009272{
9273 return (first_autopat[(int)EVENT_CMDUNDEFINED] != NULL);
9274}
9275
9276/*
9277 * Return TRUE when there is an FuncUndefined autocommand defined.
9278 */
9279 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009280has_funcundefined(void)
Bram Moolenaard5005162014-08-22 23:05:54 +02009281{
9282 return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
9283}
9284
Bram Moolenaar113e1072019-01-20 15:30:40 +01009285#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009286/*
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01009287 * Return TRUE when there is a TextYankPost autocommand defined.
9288 */
9289 int
9290has_textyankpost(void)
9291{
9292 return (first_autopat[(int)EVENT_TEXTYANKPOST] != NULL);
9293}
Bram Moolenaar113e1072019-01-20 15:30:40 +01009294#endif
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01009295
9296/*
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009297 * Execute autocommands for "event" and file name "fname".
9298 * Return TRUE if some commands were executed.
9299 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009300 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009301apply_autocmds_group(
9302 event_T event,
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01009303 char_u *fname, /* NULL or empty means use actual file name */
9304 char_u *fname_io, /* fname to use for <afile> on cmdline, NULL means
Bram Moolenaar071d4272004-06-13 20:20:40 +00009305 use fname */
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01009306 int force, /* when TRUE, ignore autocmd_busy */
9307 int group, /* group ID, or AUGROUP_ALL */
9308 buf_T *buf, /* buffer for <abuf> */
9309 exarg_T *eap UNUSED) /* command arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009310{
9311 char_u *sfname = NULL; /* short file name */
9312 char_u *tail;
9313 int save_changed;
9314 buf_T *old_curbuf;
9315 int retval = FALSE;
9316 char_u *save_sourcing_name;
9317 linenr_T save_sourcing_lnum;
9318 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009319 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009320 int save_autocmd_bufnr;
9321 char_u *save_autocmd_match;
9322 int save_autocmd_busy;
9323 int save_autocmd_nested;
9324 static int nesting = 0;
9325 AutoPatCmd patcmd;
9326 AutoPat *ap;
9327#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009328 sctx_T save_current_sctx;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02009329 funccal_entry_T funccal_entry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009330 char_u *save_cmdarg;
9331 long save_cmdbang;
9332#endif
9333 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00009334#ifdef FEAT_PROFILE
9335 proftime_T wait_time;
9336#endif
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009337 int did_save_redobuff = FALSE;
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009338 save_redo_T save_redo;
Bram Moolenaarc9e9c712017-11-09 12:29:35 +01009339 int save_KeyTyped = KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009340
9341 /*
9342 * Quickly return if there are no autocommands for this event or
9343 * autocommands are blocked.
9344 */
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02009345 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
9346 || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009347 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009348
9349 /*
9350 * When autocommands are busy, new autocommands are only executed when
9351 * explicitly enabled with the "nested" flag.
9352 */
9353 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009354 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009355
9356#ifdef FEAT_EVAL
9357 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00009358 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00009359 * occurred or an exception was thrown but not caught.
9360 */
9361 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009362 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009363#endif
9364
9365 /*
9366 * FileChangedShell never nests, because it can create an endless loop.
9367 */
Bram Moolenaar56718732006-03-15 22:53:57 +00009368 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
9369 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009370 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009371
9372 /*
9373 * Ignore events in 'eventignore'.
9374 */
9375 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009376 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009377
9378 /*
9379 * Allow nesting of autocommands, but restrict the depth, because it's
9380 * possible to create an endless loop.
9381 */
9382 if (nesting == 10)
9383 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009384 emsg(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009385 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009386 }
9387
9388 /*
9389 * Check if these autocommands are disabled. Used when doing ":all" or
9390 * ":ball".
9391 */
9392 if ( (autocmd_no_enter
9393 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
9394 || (autocmd_no_leave
9395 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009396 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009397
9398 /*
9399 * Save the autocmd_* variables and info about the current buffer.
9400 */
9401 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009402 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009403 save_autocmd_bufnr = autocmd_bufnr;
9404 save_autocmd_match = autocmd_match;
9405 save_autocmd_busy = autocmd_busy;
9406 save_autocmd_nested = autocmd_nested;
9407 save_changed = curbuf->b_changed;
9408 old_curbuf = curbuf;
9409
9410 /*
9411 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00009412 * Make a copy to avoid that changing a buffer name or directory makes it
9413 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009414 */
9415 if (fname_io == NULL)
9416 {
Bram Moolenaar60a68362018-04-30 15:40:48 +02009417 if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
9418 || event == EVENT_OPTIONSET)
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009419 autocmd_fname = NULL;
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02009420 else if (fname != NULL && !ends_excmd(*fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009421 autocmd_fname = fname;
9422 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009423 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009424 else
9425 autocmd_fname = NULL;
9426 }
9427 else
9428 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009429 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009430 autocmd_fname = vim_strsave(autocmd_fname);
9431 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009432
9433 /*
9434 * Set the buffer number to be used for <abuf>.
9435 */
9436 if (buf == NULL)
9437 autocmd_bufnr = 0;
9438 else
9439 autocmd_bufnr = buf->b_fnum;
9440
9441 /*
9442 * When the file name is NULL or empty, use the file name of buffer "buf".
9443 * Always use the full path of the file name to match with, in case
9444 * "allow_dirs" is set.
9445 */
9446 if (fname == NULL || *fname == NUL)
9447 {
9448 if (buf == NULL)
9449 fname = NULL;
9450 else
9451 {
9452#ifdef FEAT_SYN_HL
9453 if (event == EVENT_SYNTAX)
9454 fname = buf->b_p_syn;
9455 else
9456#endif
9457 if (event == EVENT_FILETYPE)
9458 fname = buf->b_p_ft;
9459 else
9460 {
9461 if (buf->b_sfname != NULL)
9462 sfname = vim_strsave(buf->b_sfname);
9463 fname = buf->b_ffname;
9464 }
9465 }
9466 if (fname == NULL)
9467 fname = (char_u *)"";
9468 fname = vim_strsave(fname); /* make a copy, so we can change it */
9469 }
9470 else
9471 {
9472 sfname = vim_strsave(fname);
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009473 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
Bram Moolenaarb7407d32018-02-03 17:36:27 +01009474 * ColorScheme, QuickFixCmd* or DirChanged */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009475 if (event == EVENT_FILETYPE
9476 || event == EVENT_SYNTAX
Bram Moolenaara4baf5b2018-04-22 13:27:44 +02009477 || event == EVENT_CMDLINECHANGED
9478 || event == EVENT_CMDLINEENTER
9479 || event == EVENT_CMDLINELEAVE
9480 || event == EVENT_CMDWINENTER
9481 || event == EVENT_CMDWINLEAVE
9482 || event == EVENT_CMDUNDEFINED
Bram Moolenaar5135d462009-04-29 16:03:38 +00009483 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009484 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009485 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009486 || event == EVENT_QUICKFIXCMDPRE
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009487 || event == EVENT_COLORSCHEME
Bram Moolenaar60a68362018-04-30 15:40:48 +02009488 || event == EVENT_COLORSCHEMEPRE
Bram Moolenaar53744302015-07-17 17:38:22 +02009489 || event == EVENT_OPTIONSET
Bram Moolenaarb7407d32018-02-03 17:36:27 +01009490 || event == EVENT_QUICKFIXCMDPOST
9491 || event == EVENT_DIRCHANGED)
Bram Moolenaara4baf5b2018-04-22 13:27:44 +02009492 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00009493 fname = vim_strsave(fname);
Bram Moolenaara4baf5b2018-04-22 13:27:44 +02009494 autocmd_fname_full = TRUE; /* don't expand it later */
9495 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009496 else
9497 fname = FullName_save(fname, FALSE);
9498 }
9499 if (fname == NULL) /* out of memory */
9500 {
9501 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009502 retval = FALSE;
9503 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009504 }
9505
9506#ifdef BACKSLASH_IN_FILENAME
9507 /*
9508 * Replace all backslashes with forward slashes. This makes the
9509 * autocommand patterns portable between Unix and MS-DOS.
9510 */
9511 if (sfname != NULL)
9512 forward_slash(sfname);
9513 forward_slash(fname);
9514#endif
9515
9516#ifdef VMS
9517 /* remove version for correct match */
9518 if (sfname != NULL)
9519 vms_remove_version(sfname);
9520 vms_remove_version(fname);
9521#endif
9522
9523 /*
9524 * Set the name to be used for <amatch>.
9525 */
9526 autocmd_match = fname;
9527
9528
Bram Moolenaar8c555332018-06-22 21:30:31 +02009529 /* Don't redraw while doing autocommands. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009530 ++RedrawingDisabled;
9531 save_sourcing_name = sourcing_name;
9532 sourcing_name = NULL; /* don't free this one */
9533 save_sourcing_lnum = sourcing_lnum;
9534 sourcing_lnum = 0; /* no line number here */
9535
9536#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009537 save_current_sctx = current_sctx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009538
Bram Moolenaar05159a02005-02-26 23:04:13 +00009539# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009540 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009541 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9542# endif
9543
Bram Moolenaar27e80c82018-10-14 21:41:01 +02009544 // Don't use local function variables, if called from a function.
9545 save_funccal(&funccal_entry);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009546#endif
9547
9548 /*
9549 * When starting to execute autocommands, save the search patterns.
9550 */
9551 if (!autocmd_busy)
9552 {
9553 save_search_patterns();
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01009554#ifdef FEAT_INS_EXPAND
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009555 if (!ins_compl_active())
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01009556#endif
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009557 {
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009558 saveRedobuff(&save_redo);
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009559 did_save_redobuff = TRUE;
9560 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009561 did_filetype = keep_filetype;
9562 }
9563
9564 /*
9565 * Note that we are applying autocmds. Some commands need to know.
9566 */
9567 autocmd_busy = TRUE;
9568 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9569 ++nesting; /* see matching decrement below */
9570
9571 /* Remember that FileType was triggered. Used for did_filetype(). */
9572 if (event == EVENT_FILETYPE)
9573 did_filetype = TRUE;
9574
9575 tail = gettail(fname);
9576
9577 /* Find first autocommand that matches */
9578 patcmd.curpat = first_autopat[(int)event];
9579 patcmd.nextcmd = NULL;
9580 patcmd.group = group;
9581 patcmd.fname = fname;
9582 patcmd.sfname = sfname;
9583 patcmd.tail = tail;
9584 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009585 patcmd.arg_bufnr = autocmd_bufnr;
9586 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009587 auto_next_pat(&patcmd, FALSE);
9588
9589 /* found one, start executing the autocommands */
9590 if (patcmd.curpat != NULL)
9591 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009592 /* add to active_apc_list */
9593 patcmd.next = active_apc_list;
9594 active_apc_list = &patcmd;
9595
Bram Moolenaar071d4272004-06-13 20:20:40 +00009596#ifdef FEAT_EVAL
9597 /* set v:cmdarg (only when there is a matching pattern) */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02009598 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009599 if (eap != NULL)
9600 {
9601 save_cmdarg = set_cmdarg(eap, NULL);
9602 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9603 }
9604 else
9605 save_cmdarg = NULL; /* avoid gcc warning */
9606#endif
9607 retval = TRUE;
9608 /* mark the last pattern, to avoid an endless loop when more patterns
9609 * are added when executing autocommands */
9610 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9611 ap->last = FALSE;
9612 ap->last = TRUE;
9613 check_lnums(TRUE); /* make sure cursor and topline are valid */
9614 do_cmdline(NULL, getnextac, (void *)&patcmd,
9615 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9616#ifdef FEAT_EVAL
9617 if (eap != NULL)
9618 {
9619 (void)set_cmdarg(NULL, save_cmdarg);
9620 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9621 }
9622#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009623 /* delete from active_apc_list */
9624 if (active_apc_list == &patcmd) /* just in case */
9625 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009626 }
9627
9628 --RedrawingDisabled;
9629 autocmd_busy = save_autocmd_busy;
9630 filechangeshell_busy = FALSE;
9631 autocmd_nested = save_autocmd_nested;
9632 vim_free(sourcing_name);
9633 sourcing_name = save_sourcing_name;
9634 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009635 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009636 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009637 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009638 autocmd_bufnr = save_autocmd_bufnr;
9639 autocmd_match = save_autocmd_match;
9640#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009641 current_sctx = save_current_sctx;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02009642 restore_funccal();
Bram Moolenaar05159a02005-02-26 23:04:13 +00009643# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009644 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009645 prof_child_exit(&wait_time);
9646# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009647#endif
Bram Moolenaarc9e9c712017-11-09 12:29:35 +01009648 KeyTyped = save_KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009649 vim_free(fname);
9650 vim_free(sfname);
9651 --nesting; /* see matching increment above */
9652
9653 /*
9654 * When stopping to execute autocommands, restore the search patterns and
Bram Moolenaar3be85852014-06-12 14:01:31 +02009655 * the redo buffer. Free any buffers in the au_pending_free_buf list and
9656 * free any windows in the au_pending_free_win list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009657 */
9658 if (!autocmd_busy)
9659 {
9660 restore_search_patterns();
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009661 if (did_save_redobuff)
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009662 restoreRedobuff(&save_redo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009663 did_filetype = FALSE;
Bram Moolenaar4c7ab1b2014-04-06 20:45:43 +02009664 while (au_pending_free_buf != NULL)
9665 {
9666 buf_T *b = au_pending_free_buf->b_next;
9667 vim_free(au_pending_free_buf);
9668 au_pending_free_buf = b;
9669 }
Bram Moolenaar3be85852014-06-12 14:01:31 +02009670 while (au_pending_free_win != NULL)
9671 {
9672 win_T *w = au_pending_free_win->w_next;
9673 vim_free(au_pending_free_win);
9674 au_pending_free_win = w;
9675 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009676 }
9677
9678 /*
9679 * Some events don't set or reset the Changed flag.
9680 * Check if still in the same buffer!
9681 */
9682 if (curbuf == old_curbuf
9683 && (event == EVENT_BUFREADPOST
9684 || event == EVENT_BUFWRITEPOST
9685 || event == EVENT_FILEAPPENDPOST
9686 || event == EVENT_VIMLEAVE
9687 || event == EVENT_VIMLEAVEPRE))
9688 {
9689#ifdef FEAT_TITLE
9690 if (curbuf->b_changed != save_changed)
9691 need_maketitle = TRUE;
9692#endif
9693 curbuf->b_changed = save_changed;
9694 }
9695
9696 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009697
9698BYPASS_AU:
9699 /* When wiping out a buffer make sure all its buffer-local autocommands
9700 * are deleted. */
9701 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9702 aubuflocal_remove(buf);
9703
Bram Moolenaarc3691332016-04-20 12:49:49 +02009704 if (retval == OK && event == EVENT_FILETYPE)
9705 au_did_filetype = TRUE;
9706
Bram Moolenaar071d4272004-06-13 20:20:40 +00009707 return retval;
9708}
9709
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009710# ifdef FEAT_EVAL
9711static char_u *old_termresponse = NULL;
9712# endif
9713
9714/*
9715 * Block triggering autocommands until unblock_autocmd() is called.
9716 * Can be used recursively, so long as it's symmetric.
9717 */
9718 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009719block_autocmds(void)
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009720{
9721# ifdef FEAT_EVAL
9722 /* Remember the value of v:termresponse. */
9723 if (autocmd_blocked == 0)
9724 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9725# endif
9726 ++autocmd_blocked;
9727}
9728
9729 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009730unblock_autocmds(void)
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009731{
9732 --autocmd_blocked;
9733
9734# ifdef FEAT_EVAL
9735 /* When v:termresponse was set while autocommands were blocked, trigger
9736 * the autocommands now. Esp. useful when executing a shell command
9737 * during startup (vimdiff). */
9738 if (autocmd_blocked == 0
9739 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9740 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9741# endif
9742}
9743
Bram Moolenaar113e1072019-01-20 15:30:40 +01009744#if defined(FEAT_EVAL) && (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM)) \
9745 || defined(PROTO)
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009746 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009747is_autocmd_blocked(void)
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009748{
9749 return autocmd_blocked != 0;
9750}
Bram Moolenaar113e1072019-01-20 15:30:40 +01009751#endif
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009752
Bram Moolenaar071d4272004-06-13 20:20:40 +00009753/*
9754 * Find next autocommand pattern that matches.
9755 */
9756 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009757auto_next_pat(
9758 AutoPatCmd *apc,
9759 int stop_at_last) /* stop when 'last' flag is set */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009760{
9761 AutoPat *ap;
9762 AutoCmd *cp;
9763 char_u *name;
9764 char *s;
9765
Bram Moolenaard23a8232018-02-10 18:45:26 +01009766 VIM_CLEAR(sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009767
9768 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9769 {
9770 apc->curpat = NULL;
9771
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009772 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009773 * the group matches. For buffer-local autocommands only check the
9774 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009775 if (ap->pat != NULL && ap->cmds != NULL
9776 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9777 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009778 /* execution-condition */
9779 if (ap->buflocal_nr == 0
Bram Moolenaardffa5b82014-11-19 16:38:07 +01009780 ? (match_file_pat(NULL, &ap->reg_prog, apc->fname,
Bram Moolenaar748bf032005-02-02 23:04:36 +00009781 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009782 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009783 {
9784 name = event_nr2name(apc->event);
Bram Moolenaar8c555332018-06-22 21:30:31 +02009785 s = _("%s Autocommands for \"%s\"");
Bram Moolenaar071d4272004-06-13 20:20:40 +00009786 sourcing_name = alloc((unsigned)(STRLEN(s)
9787 + STRLEN(name) + ap->patlen + 1));
9788 if (sourcing_name != NULL)
9789 {
9790 sprintf((char *)sourcing_name, s,
9791 (char *)name, (char *)ap->pat);
9792 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009793 {
9794 verbose_enter();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009795 smsg(_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009796 verbose_leave();
9797 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009798 }
9799
9800 apc->curpat = ap;
9801 apc->nextcmd = ap->cmds;
9802 /* mark last command */
9803 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9804 cp->last = FALSE;
9805 cp->last = TRUE;
9806 }
9807 line_breakcheck();
9808 if (apc->curpat != NULL) /* found a match */
9809 break;
9810 }
9811 if (stop_at_last && ap->last)
9812 break;
9813 }
9814}
9815
9816/*
9817 * Get next autocommand command.
9818 * Called by do_cmdline() to get the next line for ":if".
9819 * Returns allocated string, or NULL for end of autocommands.
9820 */
Bram Moolenaar21691f82012-12-05 19:13:18 +01009821 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009822getnextac(int c UNUSED, void *cookie, int indent UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009823{
9824 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9825 char_u *retval;
9826 AutoCmd *ac;
9827
9828 /* Can be called again after returning the last line. */
9829 if (acp->curpat == NULL)
9830 return NULL;
9831
9832 /* repeat until we find an autocommand to execute */
9833 for (;;)
9834 {
9835 /* skip removed commands */
9836 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9837 if (acp->nextcmd->last)
9838 acp->nextcmd = NULL;
9839 else
9840 acp->nextcmd = acp->nextcmd->next;
9841
9842 if (acp->nextcmd != NULL)
9843 break;
9844
9845 /* at end of commands, find next pattern that matches */
9846 if (acp->curpat->last)
9847 acp->curpat = NULL;
9848 else
9849 acp->curpat = acp->curpat->next;
9850 if (acp->curpat != NULL)
9851 auto_next_pat(acp, TRUE);
9852 if (acp->curpat == NULL)
9853 return NULL;
9854 }
9855
9856 ac = acp->nextcmd;
9857
9858 if (p_verbose >= 9)
9859 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009860 verbose_enter_scroll();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009861 smsg(_("autocommand %s"), ac->cmd);
Bram Moolenaar32526b32019-01-19 17:43:09 +01009862 msg_puts("\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009863 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009864 }
9865 retval = vim_strsave(ac->cmd);
9866 autocmd_nested = ac->nested;
9867#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009868 current_sctx = ac->script_ctx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009869#endif
9870 if (ac->last)
9871 acp->nextcmd = NULL;
9872 else
9873 acp->nextcmd = ac->next;
9874 return retval;
9875}
9876
9877/*
9878 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009879 * To account for buffer-local autocommands, function needs to know
9880 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009881 */
9882 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009883has_autocmd(event_T event, char_u *sfname, buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009884{
9885 AutoPat *ap;
9886 char_u *fname;
9887 char_u *tail = gettail(sfname);
9888 int retval = FALSE;
9889
9890 fname = FullName_save(sfname, FALSE);
9891 if (fname == NULL)
9892 return FALSE;
9893
9894#ifdef BACKSLASH_IN_FILENAME
9895 /*
9896 * Replace all backslashes with forward slashes. This makes the
9897 * autocommand patterns portable between Unix and MS-DOS.
9898 */
9899 sfname = vim_strsave(sfname);
9900 if (sfname != NULL)
9901 forward_slash(sfname);
9902 forward_slash(fname);
9903#endif
9904
9905 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9906 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009907 && (ap->buflocal_nr == 0
Bram Moolenaardffa5b82014-11-19 16:38:07 +01009908 ? match_file_pat(NULL, &ap->reg_prog,
Bram Moolenaar748bf032005-02-02 23:04:36 +00009909 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009910 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009911 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009912 {
9913 retval = TRUE;
9914 break;
9915 }
9916
9917 vim_free(fname);
9918#ifdef BACKSLASH_IN_FILENAME
9919 vim_free(sfname);
9920#endif
9921
9922 return retval;
9923}
9924
9925#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9926/*
9927 * Function given to ExpandGeneric() to obtain the list of autocommand group
9928 * names.
9929 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009930 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009931get_augroup_name(expand_T *xp UNUSED, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009932{
9933 if (idx == augroups.ga_len) /* add "END" add the end */
9934 return (char_u *)"END";
9935 if (idx >= augroups.ga_len) /* end of list */
9936 return NULL;
Bram Moolenaarb62cc362016-09-03 16:43:53 +02009937 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup())
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02009938 /* skip deleted entries */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009939 return (char_u *)"";
9940 return AUGROUP_NAME(idx); /* return a name */
9941}
9942
9943static int include_groups = FALSE;
9944
9945 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009946set_context_in_autocmd(
9947 expand_T *xp,
9948 char_u *arg,
9949 int doautocmd) /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009950{
9951 char_u *p;
9952 int group;
9953
9954 /* check for a group name, skip it if present */
9955 include_groups = FALSE;
9956 p = arg;
9957 group = au_get_grouparg(&arg);
9958 if (group == AUGROUP_ERROR)
9959 return NULL;
9960 /* If there only is a group name that's what we expand. */
Bram Moolenaar1c465442017-03-12 20:10:05 +01009961 if (*arg == NUL && group != AUGROUP_ALL && !VIM_ISWHITE(arg[-1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962 {
9963 arg = p;
9964 group = AUGROUP_ALL;
9965 }
9966
9967 /* skip over event name */
Bram Moolenaar1c465442017-03-12 20:10:05 +01009968 for (p = arg; *p != NUL && !VIM_ISWHITE(*p); ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009969 if (*p == ',')
9970 arg = p + 1;
9971 if (*p == NUL)
9972 {
9973 if (group == AUGROUP_ALL)
9974 include_groups = TRUE;
9975 xp->xp_context = EXPAND_EVENTS; /* expand event name */
9976 xp->xp_pattern = arg;
9977 return NULL;
9978 }
9979
9980 /* skip over pattern */
9981 arg = skipwhite(p);
Bram Moolenaar1c465442017-03-12 20:10:05 +01009982 while (*arg && (!VIM_ISWHITE(*arg) || arg[-1] == '\\'))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009983 arg++;
9984 if (*arg)
9985 return arg; /* expand (next) command */
9986
9987 if (doautocmd)
9988 xp->xp_context = EXPAND_FILES; /* expand file names */
9989 else
9990 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9991 return NULL;
9992}
9993
9994/*
9995 * Function given to ExpandGeneric() to obtain the list of event names.
9996 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009997 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009998get_event_name(expand_T *xp UNUSED, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009999{
10000 if (idx < augroups.ga_len) /* First list group names, if wanted */
10001 {
Bram Moolenaarf2c4c392016-07-29 20:50:24 +020010002 if (!include_groups || AUGROUP_NAME(idx) == NULL
Bram Moolenaarb62cc362016-09-03 16:43:53 +020010003 || AUGROUP_NAME(idx) == get_deleted_augroup())
Bram Moolenaar071d4272004-06-13 20:20:40 +000010004 return (char_u *)""; /* skip deleted entries */
10005 return AUGROUP_NAME(idx); /* return a name */
10006 }
10007 return (char_u *)event_names[idx - augroups.ga_len].name;
10008}
10009
10010#endif /* FEAT_CMDL_COMPL */
10011
Bram Moolenaar113e1072019-01-20 15:30:40 +010010012#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010013/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010014 * Return TRUE if autocmd is supported.
10015 */
10016 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010017autocmd_supported(char_u *name)
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010018{
10019 char_u *p;
10020
10021 return (event_name2nr(name, &p) != NUM_EVENTS);
10022}
10023
10024/*
Bram Moolenaar195d6352005-12-19 22:08:24 +000010025 * Return TRUE if an autocommand is defined for a group, event and
10026 * pattern: The group can be omitted to accept any group. "event" and "pattern"
10027 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
10028 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
10029 * Used for:
10030 * exists("#Group") or
10031 * exists("#Group#Event") or
10032 * exists("#Group#Event#pat") or
10033 * exists("#Event") or
10034 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +000010035 */
10036 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010037au_exists(char_u *arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010038{
Bram Moolenaar195d6352005-12-19 22:08:24 +000010039 char_u *arg_save;
10040 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010041 char_u *event_name;
10042 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +000010043 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010044 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010045 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +000010046 int group;
10047 int retval = FALSE;
10048
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010049 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +000010050 arg_save = vim_strsave(arg);
10051 if (arg_save == NULL)
10052 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010053 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +000010054 if (p != NULL)
10055 *p++ = NUL;
10056
10057 /* First, look for an autocmd group name */
10058 group = au_find_group(arg_save);
10059 if (group == AUGROUP_ERROR)
10060 {
10061 /* Didn't match a group name, assume the first argument is an event. */
10062 group = AUGROUP_ALL;
10063 event_name = arg_save;
10064 }
10065 else
10066 {
10067 if (p == NULL)
10068 {
10069 /* "Group": group name is present and it's recognized */
10070 retval = TRUE;
10071 goto theend;
10072 }
10073
10074 /* Must be "Group#Event" or "Group#Event#pat". */
10075 event_name = p;
10076 p = vim_strchr(event_name, '#');
10077 if (p != NULL)
10078 *p++ = NUL; /* "Group#Event#pat" */
10079 }
10080
10081 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010082
10083 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010084 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010085
10086 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +000010087 if (event == NUM_EVENTS)
10088 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010089
10090 /* Find the first autocommand for this event.
10091 * If there isn't any, return FALSE;
10092 * If there is one and no pattern given, return TRUE; */
10093 ap = first_autopat[(int)event];
10094 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +000010095 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010096
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010097 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
10098 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010099 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010100 buflocal_buf = curbuf;
10101
Bram Moolenaar071d4272004-06-13 20:20:40 +000010102 /* Check if there is an autocommand with the given pattern. */
10103 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010104 /* only use a pattern when it has not been removed and has commands. */
10105 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010106 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +000010107 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010108 && (pattern == NULL
10109 || (buflocal_buf == NULL
10110 ? fnamecmp(ap->pat, pattern) == 0
10111 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +000010112 {
10113 retval = TRUE;
10114 break;
10115 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010116
Bram Moolenaar195d6352005-12-19 22:08:24 +000010117theend:
10118 vim_free(arg_save);
10119 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010120}
Bram Moolenaar113e1072019-01-20 15:30:40 +010010121#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010122
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010123
10124/*
Bram Moolenaar748bf032005-02-02 23:04:36 +000010125 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
10126 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
10127 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010128 * Used for autocommands and 'wildignore'.
10129 * Returns TRUE if there is a match, FALSE otherwise.
10130 */
Bram Moolenaardffa5b82014-11-19 16:38:07 +010010131 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010132match_file_pat(
10133 char_u *pattern, /* pattern to match with */
10134 regprog_T **prog, /* pre-compiled regprog or NULL */
10135 char_u *fname, /* full path of file name */
10136 char_u *sfname, /* short file name or NULL */
10137 char_u *tail, /* tail of path */
10138 int allow_dirs) /* allow matching with dir */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010139{
10140 regmatch_T regmatch;
10141 int result = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010142
Bram Moolenaar71afbfe2013-03-19 16:49:16 +010010143 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010144 if (prog != NULL)
10145 regmatch.regprog = *prog;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010146 else
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010147 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010148
10149 /*
10150 * Try for a match with the pattern with:
10151 * 1. the full file name, when the pattern has a '/'.
10152 * 2. the short file name, when the pattern has a '/'.
10153 * 3. the tail of the file name, when the pattern has no '/'.
10154 */
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010155 if (regmatch.regprog != NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +000010156 && ((allow_dirs
10157 && (vim_regexec(&regmatch, fname, (colnr_T)0)
10158 || (sfname != NULL
10159 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010160 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0))))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010161 result = TRUE;
10162
Bram Moolenaardffa5b82014-11-19 16:38:07 +010010163 if (prog != NULL)
10164 *prog = regmatch.regprog;
10165 else
Bram Moolenaar473de612013-06-08 18:19:48 +020010166 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010167 return result;
10168}
Bram Moolenaar071d4272004-06-13 20:20:40 +000010169
10170#if defined(FEAT_WILDIGN) || defined(PROTO)
10171/*
10172 * Return TRUE if a file matches with a pattern in "list".
10173 * "list" is a comma-separated list of patterns, like 'wildignore'.
10174 * "sfname" is the short file name or NULL, "ffname" the long file name.
10175 */
10176 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010177match_file_list(char_u *list, char_u *sfname, char_u *ffname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010178{
10179 char_u buf[100];
10180 char_u *tail;
10181 char_u *regpat;
10182 char allow_dirs;
10183 int match;
10184 char_u *p;
10185
10186 tail = gettail(sfname);
10187
10188 /* try all patterns in 'wildignore' */
10189 p = list;
10190 while (*p)
10191 {
10192 copy_option_part(&p, buf, 100, ",");
10193 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
10194 if (regpat == NULL)
10195 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +000010196 match = match_file_pat(regpat, NULL, ffname, sfname,
10197 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010198 vim_free(regpat);
10199 if (match)
10200 return TRUE;
10201 }
10202 return FALSE;
10203}
10204#endif
10205
10206/*
10207 * Convert the given pattern "pat" which has shell style wildcards in it, into
10208 * a regular expression, and return the result in allocated memory. If there
10209 * is a directory path separator to be matched, then TRUE is put in
10210 * allow_dirs, otherwise FALSE is put there -- webb.
10211 * Handle backslashes before special characters, like "\*" and "\ ".
10212 *
Bram Moolenaar071d4272004-06-13 20:20:40 +000010213 * Returns NULL when out of memory.
10214 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010215 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010216file_pat_to_reg_pat(
10217 char_u *pat,
10218 char_u *pat_end, /* first char after pattern or NULL */
10219 char *allow_dirs, /* Result passed back out in here */
10220 int no_bslash UNUSED) /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010221{
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010222 int size = 2; /* '^' at start, '$' at end */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010223 char_u *endp;
10224 char_u *reg_pat;
10225 char_u *p;
10226 int i;
10227 int nested = 0;
10228 int add_dollar = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010229
10230 if (allow_dirs != NULL)
10231 *allow_dirs = FALSE;
10232 if (pat_end == NULL)
10233 pat_end = pat + STRLEN(pat);
10234
Bram Moolenaar071d4272004-06-13 20:20:40 +000010235 for (p = pat; p < pat_end; p++)
10236 {
10237 switch (*p)
10238 {
10239 case '*':
10240 case '.':
10241 case ',':
10242 case '{':
10243 case '}':
10244 case '~':
10245 size += 2; /* extra backslash */
10246 break;
10247#ifdef BACKSLASH_IN_FILENAME
10248 case '\\':
10249 case '/':
10250 size += 4; /* could become "[\/]" */
10251 break;
10252#endif
10253 default:
10254 size++;
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010255 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010256 {
10257 ++p;
10258 ++size;
10259 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010260 break;
10261 }
10262 }
10263 reg_pat = alloc(size + 1);
10264 if (reg_pat == NULL)
10265 return NULL;
10266
Bram Moolenaar071d4272004-06-13 20:20:40 +000010267 i = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010268
10269 if (pat[0] == '*')
10270 while (pat[0] == '*' && pat < pat_end - 1)
10271 pat++;
10272 else
10273 reg_pat[i++] = '^';
10274 endp = pat_end - 1;
Bram Moolenaar8fee8782015-08-11 18:45:48 +020010275 if (endp >= pat && *endp == '*')
Bram Moolenaar071d4272004-06-13 20:20:40 +000010276 {
10277 while (endp - pat > 0 && *endp == '*')
10278 endp--;
10279 add_dollar = FALSE;
10280 }
10281 for (p = pat; *p && nested >= 0 && p <= endp; p++)
10282 {
10283 switch (*p)
10284 {
10285 case '*':
10286 reg_pat[i++] = '.';
10287 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +000010288 while (p[1] == '*') /* "**" matches like "*" */
10289 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010290 break;
10291 case '.':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010292 case '~':
10293 reg_pat[i++] = '\\';
10294 reg_pat[i++] = *p;
10295 break;
10296 case '?':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010297 reg_pat[i++] = '.';
10298 break;
10299 case '\\':
10300 if (p[1] == NUL)
10301 break;
10302#ifdef BACKSLASH_IN_FILENAME
10303 if (!no_bslash)
10304 {
10305 /* translate:
10306 * "\x" to "\\x" e.g., "dir\file"
10307 * "\*" to "\\.*" e.g., "dir\*.c"
10308 * "\?" to "\\." e.g., "dir\??.c"
10309 * "\+" to "\+" e.g., "fileX\+.c"
10310 */
10311 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
10312 && p[1] != '+')
10313 {
10314 reg_pat[i++] = '[';
10315 reg_pat[i++] = '\\';
10316 reg_pat[i++] = '/';
10317 reg_pat[i++] = ']';
10318 if (allow_dirs != NULL)
10319 *allow_dirs = TRUE;
10320 break;
10321 }
10322 }
10323#endif
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010324 /* Undo escaping from ExpandEscape():
10325 * foo\?bar -> foo?bar
10326 * foo\%bar -> foo%bar
10327 * foo\,bar -> foo,bar
10328 * foo\ bar -> foo bar
10329 * Don't unescape \, * and others that are also special in a
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010330 * regexp.
10331 * An escaped { must be unescaped since we use magic not
Bram Moolenaara946afe2013-08-02 15:22:39 +020010332 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010333 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334 if (*++p == '?'
10335#ifdef BACKSLASH_IN_FILENAME
10336 && no_bslash
10337#endif
10338 )
10339 reg_pat[i++] = '?';
10340 else
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010341 if (*p == ',' || *p == '%' || *p == '#'
Bram Moolenaar2288afe2015-08-11 16:20:05 +020010342 || vim_isspace(*p) || *p == '{' || *p == '}')
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010343 reg_pat[i++] = *p;
Bram Moolenaara946afe2013-08-02 15:22:39 +020010344 else if (*p == '\\' && p[1] == '\\' && p[2] == '{')
10345 {
10346 reg_pat[i++] = '\\';
10347 reg_pat[i++] = '{';
10348 p += 2;
10349 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010350 else
10351 {
10352 if (allow_dirs != NULL && vim_ispathsep(*p)
10353#ifdef BACKSLASH_IN_FILENAME
10354 && (!no_bslash || *p != '\\')
10355#endif
10356 )
10357 *allow_dirs = TRUE;
10358 reg_pat[i++] = '\\';
10359 reg_pat[i++] = *p;
10360 }
10361 break;
10362#ifdef BACKSLASH_IN_FILENAME
10363 case '/':
10364 reg_pat[i++] = '[';
10365 reg_pat[i++] = '\\';
10366 reg_pat[i++] = '/';
10367 reg_pat[i++] = ']';
10368 if (allow_dirs != NULL)
10369 *allow_dirs = TRUE;
10370 break;
10371#endif
10372 case '{':
10373 reg_pat[i++] = '\\';
10374 reg_pat[i++] = '(';
10375 nested++;
10376 break;
10377 case '}':
10378 reg_pat[i++] = '\\';
10379 reg_pat[i++] = ')';
10380 --nested;
10381 break;
10382 case ',':
10383 if (nested)
10384 {
10385 reg_pat[i++] = '\\';
10386 reg_pat[i++] = '|';
10387 }
10388 else
10389 reg_pat[i++] = ',';
10390 break;
10391 default:
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010392 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010393 reg_pat[i++] = *p++;
Bram Moolenaar13505972019-01-24 15:04:48 +010010394 else if (allow_dirs != NULL && vim_ispathsep(*p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010395 *allow_dirs = TRUE;
10396 reg_pat[i++] = *p;
10397 break;
10398 }
10399 }
10400 if (add_dollar)
10401 reg_pat[i++] = '$';
10402 reg_pat[i] = NUL;
10403 if (nested != 0)
10404 {
10405 if (nested < 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010406 emsg(_("E219: Missing {."));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010407 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010408 emsg(_("E220: Missing }."));
Bram Moolenaard23a8232018-02-10 18:45:26 +010010409 VIM_CLEAR(reg_pat);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010410 }
10411 return reg_pat;
10412}
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010413
10414#if defined(EINTR) || defined(PROTO)
10415/*
10416 * Version of read() that retries when interrupted by EINTR (possibly
10417 * by a SIGWINCH).
10418 */
10419 long
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010420read_eintr(int fd, void *buf, size_t bufsize)
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010421{
10422 long ret;
10423
10424 for (;;)
10425 {
10426 ret = vim_read(fd, buf, bufsize);
10427 if (ret >= 0 || errno != EINTR)
10428 break;
10429 }
10430 return ret;
10431}
10432
10433/*
10434 * Version of write() that retries when interrupted by EINTR (possibly
10435 * by a SIGWINCH).
10436 */
10437 long
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010438write_eintr(int fd, void *buf, size_t bufsize)
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010439{
10440 long ret = 0;
10441 long wlen;
10442
10443 /* Repeat the write() so long it didn't fail, other than being interrupted
10444 * by a signal. */
10445 while (ret < (long)bufsize)
10446 {
Bram Moolenaar9c263032010-12-17 18:06:06 +010010447 wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010448 if (wlen < 0)
10449 {
10450 if (errno != EINTR)
10451 break;
10452 }
10453 else
10454 ret += wlen;
10455 }
10456 return ret;
10457}
10458#endif