blob: 8798cff1b6c3a71478b0236c91c98f575b56ce3f [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
30#ifdef FEAT_MBYTE
Bram Moolenaard25c16e2016-01-29 22:13:30 +010031static char_u *next_fenc(char_u **pp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000032# ifdef FEAT_EVAL
Bram Moolenaard25c16e2016-01-29 22:13:30 +010033static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000034# endif
35#endif
36#ifdef FEAT_VIMINFO
Bram Moolenaard25c16e2016-01-29 22:13:30 +010037static void check_marks_read(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000038#endif
39#ifdef FEAT_CRYPT
Bram Moolenaar8767f522016-07-01 17:17:39 +020040static 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 +000041#endif
42#ifdef UNIX
Bram Moolenaard25c16e2016-01-29 22:13:30 +010043static void set_file_time(char_u *fname, time_t atime, time_t mtime);
Bram Moolenaar071d4272004-06-13 20:20:40 +000044#endif
Bram Moolenaard25c16e2016-01-29 22:13:30 +010045static int set_rw_fname(char_u *fname, char_u *sfname);
46static int msg_add_fileformat(int eol_type);
47static void msg_add_eol(void);
Bram Moolenaar8767f522016-07-01 17:17:39 +020048static int check_mtime(buf_T *buf, stat_T *s);
Bram Moolenaard25c16e2016-01-29 22:13:30 +010049static int time_differs(long t1, long t2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000050#ifdef FEAT_AUTOCMD
Bram Moolenaard25c16e2016-01-29 22:13:30 +010051static int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap);
52static int au_find_group(char_u *name);
Bram Moolenaar70836c82006-02-20 21:28:49 +000053
54# define AUGROUP_DEFAULT -1 /* default autocmd group */
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +000055# define AUGROUP_ERROR -2 /* erroneous autocmd group */
Bram Moolenaar70836c82006-02-20 21:28:49 +000056# define AUGROUP_ALL -3 /* all autocmd groups */
Bram Moolenaar071d4272004-06-13 20:20:40 +000057#endif
58
59#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
60# define HAS_BW_FLAGS
61# define FIO_LATIN1 0x01 /* convert Latin1 */
62# define FIO_UTF8 0x02 /* convert UTF-8 */
63# define FIO_UCS2 0x04 /* convert UCS-2 */
64# define FIO_UCS4 0x08 /* convert UCS-4 */
65# define FIO_UTF16 0x10 /* convert UTF-16 */
66# ifdef WIN3264
67# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
68# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
69# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
70# endif
Bram Moolenaard0573012017-10-28 21:11:06 +020071# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +000072# define FIO_MACROMAN 0x20 /* convert MacRoman */
73# endif
74# define FIO_ENDIAN_L 0x80 /* little endian */
75# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
76# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
77# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
78# define FIO_ALL -1 /* allow all formats */
79#endif
80
81/* When converting, a read() or write() may leave some bytes to be converted
82 * for the next call. The value is guessed... */
83#define CONV_RESTLEN 30
84
85/* We have to guess how much a sequence of bytes may expand when converting
86 * with iconv() to be able to allocate a buffer. */
87#define ICONV_MULT 8
88
89/*
90 * Structure to pass arguments from buf_write() to buf_write_bytes().
91 */
92struct bw_info
93{
94 int bw_fd; /* file descriptor */
95 char_u *bw_buf; /* buffer with data to be written */
Bram Moolenaard089d9b2007-09-30 12:02:55 +000096 int bw_len; /* length of data */
Bram Moolenaar071d4272004-06-13 20:20:40 +000097#ifdef HAS_BW_FLAGS
98 int bw_flags; /* FIO_ flags */
99#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200100#ifdef FEAT_CRYPT
101 buf_T *bw_buffer; /* buffer being written */
102#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103#ifdef FEAT_MBYTE
104 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
105 int bw_restlen; /* nr of bytes in bw_rest[] */
106 int bw_first; /* first write call */
107 char_u *bw_conv_buf; /* buffer for writing converted chars */
108 int bw_conv_buflen; /* size of bw_conv_buf */
109 int bw_conv_error; /* set for conversion error */
Bram Moolenaar32b485f2009-07-29 16:06:27 +0000110 linenr_T bw_conv_error_lnum; /* first line with error or zero */
111 linenr_T bw_start_lnum; /* line number at start of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112# ifdef USE_ICONV
113 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
114# endif
115#endif
116};
117
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100118static int buf_write_bytes(struct bw_info *ip);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119
120#ifdef FEAT_MBYTE
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100121static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp);
122static int ucs2bytes(unsigned c, char_u **pp, int flags);
123static int need_conversion(char_u *fenc);
124static int get_fio_flags(char_u *ptr);
125static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags);
126static int make_bom(char_u *buf, char_u *name);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000127# ifdef WIN3264
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100128static int get_win_fio_flags(char_u *ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000129# endif
Bram Moolenaard0573012017-10-28 21:11:06 +0200130# ifdef MACOS_CONVERT
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100131static int get_mac_fio_flags(char_u *ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000132# endif
133#endif
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100134static int move_lines(buf_T *frombuf, buf_T *tobuf);
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000135#ifdef TEMPDIRNAMES
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100136static void vim_settempdir(char_u *tempdir);
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000137#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000138#ifdef FEAT_AUTOCMD
139static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
140#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000141
Bram Moolenaarc3691332016-04-20 12:49:49 +0200142#ifdef FEAT_AUTOCMD
143/*
144 * Set by the apply_autocmds_group function if the given event is equal to
145 * EVENT_FILETYPE. Used by the readfile function in order to determine if
146 * EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
147 *
148 * Relying on this value requires one to reset it prior calling
149 * apply_autocmds_group.
150 */
151static int au_did_filetype INIT(= FALSE);
152#endif
153
Bram Moolenaar071d4272004-06-13 20:20:40 +0000154 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100155filemess(
156 buf_T *buf,
157 char_u *name,
158 char_u *s,
159 int attr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160{
161 int msg_scroll_save;
162
163 if (msg_silent != 0)
164 return;
165 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
166 /* If it's extremely long, truncate it. */
167 if (STRLEN(IObuff) > IOSIZE - 80)
168 IObuff[IOSIZE - 80] = NUL;
169 STRCAT(IObuff, s);
170 /*
171 * For the first message may have to start a new line.
172 * For further ones overwrite the previous one, reset msg_scroll before
173 * calling filemess().
174 */
175 msg_scroll_save = msg_scroll;
176 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
177 msg_scroll = FALSE;
178 if (!msg_scroll) /* wait a bit when overwriting an error msg */
179 check_for_delay(FALSE);
180 msg_start();
181 msg_scroll = msg_scroll_save;
182 msg_scrolled_ign = TRUE;
183 /* may truncate the message to avoid a hit-return prompt */
184 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
185 msg_clr_eos();
186 out_flush();
187 msg_scrolled_ign = FALSE;
188}
189
190/*
191 * Read lines from file "fname" into the buffer after line "from".
192 *
193 * 1. We allocate blocks with lalloc, as big as possible.
194 * 2. Each block is filled with characters from the file with a single read().
195 * 3. The lines are inserted in the buffer with ml_append().
196 *
197 * (caller must check that fname != NULL, unless READ_STDIN is used)
198 *
199 * "lines_to_skip" is the number of lines that must be skipped
200 * "lines_to_read" is the number of lines that are appended
201 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
202 *
203 * flags:
204 * READ_NEW starting to edit a new buffer
205 * READ_FILTER reading filter output
206 * READ_STDIN read from stdin instead of a file
207 * READ_BUFFER read from curbuf instead of a file (converting after reading
208 * stdin)
209 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
Bram Moolenaar59f931e2010-07-24 20:27:03 +0200210 * READ_KEEP_UNDO don't clear undo info or read it from a file
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200211 * READ_FIFO read from fifo/socket instead of a file
Bram Moolenaar071d4272004-06-13 20:20:40 +0000212 *
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100213 * return FAIL for failure, NOTDONE for directory (failure), or OK
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214 */
215 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +0100216readfile(
217 char_u *fname,
218 char_u *sfname,
219 linenr_T from,
220 linenr_T lines_to_skip,
221 linenr_T lines_to_read,
222 exarg_T *eap, /* can be NULL! */
223 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224{
225 int fd = 0;
226 int newfile = (flags & READ_NEW);
227 int check_readonly;
228 int filtering = (flags & READ_FILTER);
229 int read_stdin = (flags & READ_STDIN);
230 int read_buffer = (flags & READ_BUFFER);
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200231 int read_fifo = (flags & READ_FIFO);
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000232 int set_options = newfile || read_buffer
233 || (eap != NULL && eap->read_edit);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000234 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
235 colnr_T read_buf_col = 0; /* next char to read from this line */
236 char_u c;
237 linenr_T lnum = from;
238 char_u *ptr = NULL; /* pointer into read buffer */
239 char_u *buffer = NULL; /* read buffer */
240 char_u *new_buffer = NULL; /* init to shut up gcc */
241 char_u *line_start = NULL; /* init to shut up gcc */
242 int wasempty; /* buffer was empty before reading */
243 colnr_T len;
244 long size = 0;
245 char_u *p;
Bram Moolenaar8767f522016-07-01 17:17:39 +0200246 off_T filesize = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 int skip_read = FALSE;
248#ifdef FEAT_CRYPT
249 char_u *cryptkey = NULL;
Bram Moolenaarf50a2532010-05-21 15:36:08 +0200250 int did_ask_for_key = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +0200252#ifdef FEAT_PERSISTENT_UNDO
253 context_sha256_T sha_ctx;
254 int read_undo_file = FALSE;
255#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256 int split = 0; /* number of split lines */
257#define UNKNOWN 0x0fffffff /* file size is unknown */
258 linenr_T linecnt;
259 int error = FALSE; /* errors encountered */
260 int ff_error = EOL_UNKNOWN; /* file format with errors */
261 long linerest = 0; /* remaining chars in line */
262#ifdef UNIX
263 int perm = 0;
264 int swap_mode = -1; /* protection bits for swap file */
265#else
266 int perm;
267#endif
268 int fileformat = 0; /* end-of-line format */
269 int keep_fileformat = FALSE;
Bram Moolenaar8767f522016-07-01 17:17:39 +0200270 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000271 int file_readonly;
272 linenr_T skip_count = 0;
273 linenr_T read_count = 0;
274 int msg_save = msg_scroll;
275 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
276 * last read was missing the eol */
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100277 int try_mac;
278 int try_dos;
279 int try_unix;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000280 int file_rewind = FALSE;
281#ifdef FEAT_MBYTE
282 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000283 linenr_T conv_error = 0; /* line nr with conversion error */
284 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000285 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
286 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000287 int bad_char_behavior = BAD_REPLACE;
288 /* BAD_KEEP, BAD_DROP or character to
289 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000290 char_u *tmpname = NULL; /* name of 'charconvert' output file */
291 int fio_flags = 0;
292 char_u *fenc; /* fileencoding to use */
293 int fenc_alloced; /* fenc_next is in allocated memory */
294 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
295 int advance_fenc = FALSE;
296 long real_size = 0;
297# ifdef USE_ICONV
298 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
299# ifdef FEAT_EVAL
300 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
301 'charconvert' next */
302# endif
303# endif
304 int converted = FALSE; /* TRUE if conversion done */
305 int notconverted = FALSE; /* TRUE if conversion wanted but it
306 wasn't possible */
307 char_u conv_rest[CONV_RESTLEN];
308 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
309#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000310#ifdef FEAT_AUTOCMD
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200311 buf_T *old_curbuf;
312 char_u *old_b_ffname;
313 char_u *old_b_fname;
314 int using_b_ffname;
315 int using_b_fname;
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000316#endif
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200317
Bram Moolenaarc3691332016-04-20 12:49:49 +0200318#ifdef FEAT_AUTOCMD
319 au_did_filetype = FALSE; /* reset before triggering any autocommands */
320#endif
321
Bram Moolenaarcab35ad2011-02-15 17:39:22 +0100322 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000323
324 /*
325 * If there is no file name yet, use the one for the read file.
326 * BF_NOTEDITED is set to reflect this.
327 * Don't do this for a read from a filter.
328 * Only do this when 'cpoptions' contains the 'f' flag.
329 */
330 if (curbuf->b_ffname == NULL
331 && !filtering
332 && fname != NULL
333 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
334 && !(flags & READ_DUMMY))
335 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000336 if (set_rw_fname(fname, sfname) == FAIL)
337 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338 }
339
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200340#ifdef FEAT_AUTOCMD
341 /* Remember the initial values of curbuf, curbuf->b_ffname and
342 * curbuf->b_fname to detect whether they are altered as a result of
343 * executing nasty autocommands. Also check if "fname" and "sfname"
344 * point to one of these values. */
345 old_curbuf = curbuf;
346 old_b_ffname = curbuf->b_ffname;
347 old_b_fname = curbuf->b_fname;
348 using_b_ffname = (fname == curbuf->b_ffname)
349 || (sfname == curbuf->b_ffname);
350 using_b_fname = (fname == curbuf->b_fname) || (sfname == curbuf->b_fname);
351#endif
352
Bram Moolenaardf177f62005-02-22 08:39:57 +0000353 /* After reading a file the cursor line changes but we don't want to
354 * display the line. */
355 ex_no_reprint = TRUE;
356
Bram Moolenaar55b7cf82006-09-09 12:52:42 +0000357 /* don't display the file info for another buffer now */
358 need_fileinfo = FALSE;
359
Bram Moolenaar071d4272004-06-13 20:20:40 +0000360 /*
361 * For Unix: Use the short file name whenever possible.
362 * Avoids problems with networks and when directory names are changed.
363 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
364 * another directory, which we don't detect.
365 */
366 if (sfname == NULL)
367 sfname = fname;
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200368#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 fname = sfname;
370#endif
371
372#ifdef FEAT_AUTOCMD
373 /*
374 * The BufReadCmd and FileReadCmd events intercept the reading process by
375 * executing the associated commands instead.
376 */
377 if (!filtering && !read_stdin && !read_buffer)
378 {
379 pos_T pos;
380
381 pos = curbuf->b_op_start;
382
383 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
384 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
385 curbuf->b_op_start.col = 0;
386
387 if (newfile)
388 {
389 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
390 FALSE, curbuf, eap))
391#ifdef FEAT_EVAL
392 return aborting() ? FAIL : OK;
393#else
394 return OK;
395#endif
396 }
397 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
398 FALSE, NULL, eap))
399#ifdef FEAT_EVAL
400 return aborting() ? FAIL : OK;
401#else
402 return OK;
403#endif
404
405 curbuf->b_op_start = pos;
406 }
407#endif
408
409 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
410 msg_scroll = FALSE; /* overwrite previous file message */
411 else
412 msg_scroll = TRUE; /* don't overwrite previous file message */
413
414 /*
415 * If the name ends in a path separator, we can't open it. Check here,
416 * because reading the file may actually work, but then creating the swap
417 * file may destroy it! Reported on MS-DOS and Win 95.
418 * If the name is too long we might crash further on, quit here.
419 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000420 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000421 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000422 p = fname + STRLEN(fname);
423 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000424 {
425 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
426 msg_end();
427 msg_scroll = msg_save;
428 return FAIL;
429 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 }
431
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200432 if (!read_stdin && !read_buffer && !read_fifo)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433 {
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200434#ifdef UNIX
435 /*
436 * On Unix it is possible to read a directory, so we have to
437 * check for it before the mch_open().
438 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000439 perm = mch_getperm(fname);
440 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
441# ifdef S_ISFIFO
442 && !S_ISFIFO(perm) /* ... or fifo */
443# endif
444# ifdef S_ISSOCK
445 && !S_ISSOCK(perm) /* ... or socket */
446# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +0000447# ifdef OPEN_CHR_FILES
448 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
449 /* ... or a character special file named /dev/fd/<n> */
450# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451 )
452 {
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100453 int retval = FAIL;
454
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455 if (S_ISDIR(perm))
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100456 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000457 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100458 retval = NOTDONE;
459 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460 else
461 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
462 msg_end();
463 msg_scroll = msg_save;
Bram Moolenaare13b9af2017-01-13 22:01:02 +0100464 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000465 }
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200466#endif
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100467#if defined(MSWIN)
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000468 /*
469 * MS-Windows allows opening a device, but we will probably get stuck
470 * trying to read it.
471 */
472 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
473 {
Bram Moolenaar5386a122007-06-28 20:02:32 +0000474 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000475 msg_end();
476 msg_scroll = msg_save;
477 return FAIL;
478 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000479#endif
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200480 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000481
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200482 /* Set default or forced 'fileformat' and 'binary'. */
483 set_file_options(set_options, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000484
485 /*
486 * When opening a new file we take the readonly flag from the file.
487 * Default is r/w, can be set to r/o below.
488 * Don't reset it when in readonly mode
489 * Only set/reset b_p_ro when BF_CHECK_RO is set.
490 */
491 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000492 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 curbuf->b_p_ro = FALSE;
494
Bram Moolenaarf71d7b92016-08-09 22:14:05 +0200495 if (newfile && !read_stdin && !read_buffer && !read_fifo)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496 {
Bram Moolenaare60acc12011-05-10 16:41:25 +0200497 /* Remember time of file. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000498 if (mch_stat((char *)fname, &st) >= 0)
499 {
500 buf_store_time(curbuf, &st, fname);
501 curbuf->b_mtime_read = curbuf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502#ifdef UNIX
503 /*
504 * Use the protection bits of the original file for the swap file.
505 * This makes it possible for others to read the name of the
506 * edited file from the swapfile, but only if they can read the
507 * edited file.
508 * Remove the "write" and "execute" bits for group and others
509 * (they must not write the swapfile).
510 * Add the "read" and "write" bits for the user, otherwise we may
511 * not be able to write to the file ourselves.
512 * Setting the bits is done below, after creating the swap file.
513 */
514 swap_mode = (st.st_mode & 0644) | 0600;
515#endif
516#ifdef FEAT_CW_EDITOR
517 /* Get the FSSpec on MacOS
518 * TODO: Update it properly when the buffer name changes
519 */
520 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
521#endif
522#ifdef VMS
523 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000524 curbuf->b_fab_rat = st.st_fab_rat;
525 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526#endif
527 }
528 else
529 {
530 curbuf->b_mtime = 0;
531 curbuf->b_mtime_read = 0;
532 curbuf->b_orig_size = 0;
533 curbuf->b_orig_mode = 0;
534 }
535
536 /* Reset the "new file" flag. It will be set again below when the
537 * file doesn't exist. */
538 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
539 }
540
541/*
542 * for UNIX: check readonly with perm and mch_access()
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100543 * for Amiga: check readonly by trying to open the file for writing
Bram Moolenaar071d4272004-06-13 20:20:40 +0000544 */
545 file_readonly = FALSE;
546 if (read_stdin)
547 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100548#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
550 setmode(0, O_BINARY);
551#endif
552 }
553 else if (!read_buffer)
554 {
555#ifdef USE_MCH_ACCESS
556 if (
557# ifdef UNIX
558 !(perm & 0222) ||
559# endif
560 mch_access((char *)fname, W_OK))
561 file_readonly = TRUE;
562 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
563#else
564 if (!newfile
565 || readonlymode
566 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
567 {
568 file_readonly = TRUE;
569 /* try to open ro */
570 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
571 }
572#endif
573 }
574
575 if (fd < 0) /* cannot open at all */
576 {
577#ifndef UNIX
578 int isdir_f;
579#endif
580 msg_scroll = msg_save;
581#ifndef UNIX
582 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100583 * On Amiga we can't open a directory, check here.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000584 */
585 isdir_f = (mch_isdir(fname));
586 perm = mch_getperm(fname); /* check if the file exists */
587 if (isdir_f)
588 {
589 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
590 curbuf->b_p_ro = TRUE; /* must use "w!" now */
591 }
592 else
593#endif
594 if (newfile)
595 {
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200596 if (perm < 0
597#ifdef ENOENT
598 && errno == ENOENT
599#endif
600 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000601 {
602 /*
603 * Set the 'new-file' flag, so that when the file has
604 * been created by someone else, a ":w" will complain.
605 */
606 curbuf->b_flags |= BF_NEW;
607
608 /* Create a swap file now, so that other Vims are warned
609 * that we are editing this file. Don't do this for a
610 * "nofile" or "nowrite" buffer type. */
611#ifdef FEAT_QUICKFIX
612 if (!bt_dontwrite(curbuf))
613#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000614 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000616#ifdef FEAT_AUTOCMD
617 /* SwapExists autocommand may mess things up */
618 if (curbuf != old_curbuf
619 || (using_b_ffname
620 && (old_b_ffname != curbuf->b_ffname))
621 || (using_b_fname
622 && (old_b_fname != curbuf->b_fname)))
623 {
624 EMSG(_(e_auchangedbuf));
625 return FAIL;
626 }
627#endif
628 }
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000629 if (dir_of_file_exists(fname))
630 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
631 else
632 filemess(curbuf, sfname,
633 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634#ifdef FEAT_VIMINFO
635 /* Even though this is a new file, it might have been
636 * edited before and deleted. Get the old marks. */
637 check_marks_read();
638#endif
639#ifdef FEAT_MBYTE
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200640 /* Set forced 'fileencoding'. */
641 if (eap != NULL)
642 set_forced_fenc(eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000643#endif
644#ifdef FEAT_AUTOCMD
645 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
646 FALSE, curbuf, eap);
647#endif
648 /* remember the current fileformat */
649 save_file_ff(curbuf);
650
651#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
652 if (aborting()) /* autocmds may abort script processing */
653 return FAIL;
654#endif
655 return OK; /* a new file is not an error */
656 }
657 else
658 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000659 filemess(curbuf, sfname, (char_u *)(
660# ifdef EFBIG
661 (errno == EFBIG) ? _("[File too big]") :
662# endif
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200663# ifdef EOVERFLOW
664 (errno == EOVERFLOW) ? _("[File too big]") :
665# endif
Bram Moolenaar202795b2005-10-11 20:29:39 +0000666 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 curbuf->b_p_ro = TRUE; /* must use "w!" now */
668 }
669 }
670
671 return FAIL;
672 }
673
674 /*
675 * Only set the 'ro' flag for readonly files the first time they are
676 * loaded. Help files always get readonly mode
677 */
678 if ((check_readonly && file_readonly) || curbuf->b_help)
679 curbuf->b_p_ro = TRUE;
680
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000681 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 {
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000683 /* Don't change 'eol' if reading from buffer as it will already be
684 * correctly set when reading stdin. */
685 if (!read_buffer)
686 {
687 curbuf->b_p_eol = TRUE;
688 curbuf->b_start_eol = TRUE;
689 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690#ifdef FEAT_MBYTE
691 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000692 curbuf->b_start_bomb = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000693#endif
694 }
695
696 /* Create a swap file now, so that other Vims are warned that we are
697 * editing this file.
698 * Don't do this for a "nofile" or "nowrite" buffer type. */
699#ifdef FEAT_QUICKFIX
700 if (!bt_dontwrite(curbuf))
701#endif
702 {
703 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000704#ifdef FEAT_AUTOCMD
705 if (!read_stdin && (curbuf != old_curbuf
706 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
707 || (using_b_fname && (old_b_fname != curbuf->b_fname))))
708 {
709 EMSG(_(e_auchangedbuf));
710 if (!read_buffer)
711 close(fd);
712 return FAIL;
713 }
714#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715#ifdef UNIX
716 /* Set swap file protection bits after creating it. */
Bram Moolenaarf061e0b2009-06-24 15:32:01 +0000717 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
718 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
Bram Moolenaar5a73e0c2017-11-04 21:35:01 +0100719 {
720 char_u *swap_fname = curbuf->b_ml.ml_mfp->mf_fname;
721
722 /*
723 * If the group-read bit is set but not the world-read bit, then
724 * the group must be equal to the group of the original file. If
725 * we can't make that happen then reset the group-read bit. This
726 * avoids making the swap file readable to more users when the
727 * primary group of the user is too permissive.
728 */
729 if ((swap_mode & 044) == 040)
730 {
731 stat_T swap_st;
732
733 if (mch_stat((char *)swap_fname, &swap_st) >= 0
734 && st.st_gid != swap_st.st_gid
735 && fchown(curbuf->b_ml.ml_mfp->mf_fd, -1, st.st_gid)
736 == -1)
737 swap_mode &= 0600;
738 }
739
740 (void)mch_setperm(swap_fname, (long)swap_mode);
741 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742#endif
743 }
744
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000745#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000746 /* If "Quit" selected at ATTENTION dialog, don't load the file */
747 if (swap_exists_action == SEA_QUIT)
748 {
749 if (!read_buffer && !read_stdin)
750 close(fd);
751 return FAIL;
752 }
753#endif
754
755 ++no_wait_return; /* don't wait for return yet */
756
757 /*
758 * Set '[ mark to the line above where the lines go (line 1 if zero).
759 */
760 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
761 curbuf->b_op_start.col = 0;
762
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100763 try_mac = (vim_strchr(p_ffs, 'm') != NULL);
764 try_dos = (vim_strchr(p_ffs, 'd') != NULL);
765 try_unix = (vim_strchr(p_ffs, 'x') != NULL);
766
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767#ifdef FEAT_AUTOCMD
768 if (!read_buffer)
769 {
770 int m = msg_scroll;
771 int n = msg_scrolled;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000772
773 /*
774 * The file must be closed again, the autocommands may want to change
775 * the file before reading it.
776 */
777 if (!read_stdin)
778 close(fd); /* ignore errors */
779
780 /*
781 * The output from the autocommands should not overwrite anything and
782 * should not be overwritten: Set msg_scroll, restore its value if no
783 * output was done.
784 */
785 msg_scroll = TRUE;
786 if (filtering)
787 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
788 FALSE, curbuf, eap);
789 else if (read_stdin)
790 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
791 FALSE, curbuf, eap);
792 else if (newfile)
793 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
794 FALSE, curbuf, eap);
795 else
796 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
797 FALSE, NULL, eap);
Bram Moolenaar7a2699e2017-01-23 21:31:09 +0100798 /* autocommands may have changed it */
799 try_mac = (vim_strchr(p_ffs, 'm') != NULL);
800 try_dos = (vim_strchr(p_ffs, 'd') != NULL);
801 try_unix = (vim_strchr(p_ffs, 'x') != NULL);
802
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 if (msg_scrolled == n)
804 msg_scroll = m;
805
806#ifdef FEAT_EVAL
807 if (aborting()) /* autocmds may abort script processing */
808 {
809 --no_wait_return;
810 msg_scroll = msg_save;
811 curbuf->b_p_ro = TRUE; /* must use "w!" now */
812 return FAIL;
813 }
814#endif
815 /*
816 * Don't allow the autocommands to change the current buffer.
817 * Try to re-open the file.
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000818 *
819 * Don't allow the autocommands to change the buffer name either
820 * (cd for example) if it invalidates fname or sfname.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000821 */
822 if (!read_stdin && (curbuf != old_curbuf
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000823 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
824 || (using_b_fname && (old_b_fname != curbuf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
826 {
827 --no_wait_return;
828 msg_scroll = msg_save;
829 if (fd < 0)
830 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
831 else
832 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
833 curbuf->b_p_ro = TRUE; /* must use "w!" now */
834 return FAIL;
835 }
836 }
837#endif /* FEAT_AUTOCMD */
838
839 /* Autocommands may add lines to the file, need to check if it is empty */
840 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
841
842 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
843 {
844 /*
845 * Show the user that we are busy reading the input. Sometimes this
846 * may take a while. When reading from stdin another program may
847 * still be running, don't move the cursor to the last line, unless
848 * always using the GUI.
849 */
850 if (read_stdin)
851 {
Bram Moolenaar234d1622017-11-18 14:55:23 +0100852 if (!is_not_a_term())
853 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854#ifndef ALWAYS_USE_GUI
Bram Moolenaar234d1622017-11-18 14:55:23 +0100855 mch_msg(_("Vim: Reading from stdin...\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856#endif
857#ifdef FEAT_GUI
Bram Moolenaar234d1622017-11-18 14:55:23 +0100858 /* Also write a message in the GUI window, if there is one. */
859 if (gui.in_use && !gui.dying && !gui.starting)
860 {
861 p = (char_u *)_("Reading from stdin...");
862 gui_write(p, (int)STRLEN(p));
863 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000864#endif
Bram Moolenaar234d1622017-11-18 14:55:23 +0100865 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 }
867 else if (!read_buffer)
868 filemess(curbuf, sfname, (char_u *)"", 0);
869 }
870
871 msg_scroll = FALSE; /* overwrite the file message */
872
873 /*
874 * Set linecnt now, before the "retry" caused by a wrong guess for
875 * fileformat, and after the autocommands, which may change them.
876 */
877 linecnt = curbuf->b_ml.ml_line_count;
878
879#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000880 /* "++bad=" argument. */
881 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000882 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000883 bad_char_behavior = eap->bad_char;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000884 if (set_options)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000885 curbuf->b_bad_char = eap->bad_char;
886 }
887 else
888 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000889
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000891 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892 */
893 if (eap != NULL && eap->force_enc != 0)
894 {
895 fenc = enc_canonize(eap->cmd + eap->force_enc);
896 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000897 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 }
899 else if (curbuf->b_p_bin)
900 {
901 fenc = (char_u *)""; /* binary: don't convert */
902 fenc_alloced = FALSE;
903 }
904 else if (curbuf->b_help)
905 {
906 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000907 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908
909 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
910 * fails it must be latin1.
911 * Always do this when 'encoding' is "utf-8". Otherwise only do
912 * this when needed to avoid [converted] remarks all the time.
913 * It is needed when the first line contains non-ASCII characters.
914 * That is only in *.??x files. */
915 fenc = (char_u *)"latin1";
916 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000917 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000919 fc = fname[STRLEN(fname) - 1];
920 if (TOLOWER_ASC(fc) == 'x')
921 {
922 /* Read the first line (and a bit more). Immediately rewind to
923 * the start of the file. If the read() fails "len" is -1. */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +0100924 len = read_eintr(fd, firstline, 80);
Bram Moolenaar8767f522016-07-01 17:17:39 +0200925 vim_lseek(fd, (off_T)0L, SEEK_SET);
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000926 for (p = firstline; p < firstline + len; ++p)
927 if (*p >= 0x80)
928 {
929 c = TRUE;
930 break;
931 }
932 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 }
934
935 if (c)
936 {
937 fenc_next = fenc;
938 fenc = (char_u *)"utf-8";
939
940 /* When the file is utf-8 but a character doesn't fit in
941 * 'encoding' don't retry. In help text editing utf-8 bytes
942 * doesn't make sense. */
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000943 if (!enc_utf8)
944 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945 }
946 fenc_alloced = FALSE;
947 }
948 else if (*p_fencs == NUL)
949 {
950 fenc = curbuf->b_p_fenc; /* use format from buffer */
951 fenc_alloced = FALSE;
952 }
953 else
954 {
955 fenc_next = p_fencs; /* try items in 'fileencodings' */
956 fenc = next_fenc(&fenc_next);
957 fenc_alloced = TRUE;
958 }
959#endif
960
961 /*
962 * Jump back here to retry reading the file in different ways.
963 * Reasons to retry:
964 * - encoding conversion failed: try another one from "fenc_next"
965 * - BOM detected and fenc was set, need to setup conversion
966 * - "fileformat" check failed: try another
967 *
968 * Variables set for special retry actions:
969 * "file_rewind" Rewind the file to start reading it again.
970 * "advance_fenc" Advance "fenc" using "fenc_next".
971 * "skip_read" Re-use already read bytes (BOM detected).
972 * "did_iconv" iconv() conversion failed, try 'charconvert'.
973 * "keep_fileformat" Don't reset "fileformat".
974 *
975 * Other status indicators:
976 * "tmpname" When != NULL did conversion with 'charconvert'.
977 * Output file has to be deleted afterwards.
978 * "iconv_fd" When != -1 did conversion with iconv().
979 */
980retry:
981
982 if (file_rewind)
983 {
984 if (read_buffer)
985 {
986 read_buf_lnum = 1;
987 read_buf_col = 0;
988 }
Bram Moolenaar8767f522016-07-01 17:17:39 +0200989 else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 {
991 /* Can't rewind the file, give up. */
992 error = TRUE;
993 goto failed;
994 }
995 /* Delete the previously read lines. */
996 while (lnum > from)
997 ml_delete(lnum--, FALSE);
998 file_rewind = FALSE;
999#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001000 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001001 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001003 curbuf->b_start_bomb = FALSE;
1004 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001005 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001006#endif
1007 }
1008
1009 /*
1010 * When retrying with another "fenc" and the first time "fileformat"
1011 * will be reset.
1012 */
1013 if (keep_fileformat)
1014 keep_fileformat = FALSE;
1015 else
1016 {
1017 if (eap != NULL && eap->force_ff != 0)
Bram Moolenaar1c860362008-11-12 15:05:21 +00001018 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 fileformat = get_fileformat_force(curbuf, eap);
Bram Moolenaar1c860362008-11-12 15:05:21 +00001020 try_unix = try_dos = try_mac = FALSE;
1021 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 else if (curbuf->b_p_bin)
1023 fileformat = EOL_UNIX; /* binary: use Unix format */
1024 else if (*p_ffs == NUL)
1025 fileformat = get_fileformat(curbuf);/* use format from buffer */
1026 else
1027 fileformat = EOL_UNKNOWN; /* detect from file */
1028 }
1029
1030#ifdef FEAT_MBYTE
1031# ifdef USE_ICONV
1032 if (iconv_fd != (iconv_t)-1)
1033 {
1034 /* aborted conversion with iconv(), close the descriptor */
1035 iconv_close(iconv_fd);
1036 iconv_fd = (iconv_t)-1;
1037 }
1038# endif
1039
1040 if (advance_fenc)
1041 {
1042 /*
1043 * Try the next entry in 'fileencodings'.
1044 */
1045 advance_fenc = FALSE;
1046
1047 if (eap != NULL && eap->force_enc != 0)
1048 {
1049 /* Conversion given with "++cc=" wasn't possible, read
1050 * without conversion. */
1051 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001052 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053 if (fenc_alloced)
1054 vim_free(fenc);
1055 fenc = (char_u *)"";
1056 fenc_alloced = FALSE;
1057 }
1058 else
1059 {
1060 if (fenc_alloced)
1061 vim_free(fenc);
1062 if (fenc_next != NULL)
1063 {
1064 fenc = next_fenc(&fenc_next);
1065 fenc_alloced = (fenc_next != NULL);
1066 }
1067 else
1068 {
1069 fenc = (char_u *)"";
1070 fenc_alloced = FALSE;
1071 }
1072 }
1073 if (tmpname != NULL)
1074 {
1075 mch_remove(tmpname); /* delete converted file */
Bram Moolenaard23a8232018-02-10 18:45:26 +01001076 VIM_CLEAR(tmpname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001077 }
1078 }
1079
1080 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001081 * Conversion may be required when the encoding of the file is different
1082 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001083 */
1084 fio_flags = 0;
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001085 converted = need_conversion(fenc);
1086 if (converted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 {
1088
1089 /* "ucs-bom" means we need to check the first bytes of the file
1090 * for a BOM. */
1091 if (STRCMP(fenc, ENC_UCSBOM) == 0)
1092 fio_flags = FIO_UCSBOM;
1093
1094 /*
1095 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
1096 * done. This is handled below after read(). Prepare the
1097 * fio_flags to avoid having to parse the string each time.
1098 * Also check for Unicode to Latin1 conversion, because iconv()
1099 * appears not to handle this correctly. This works just like
1100 * conversion to UTF-8 except how the resulting character is put in
1101 * the buffer.
1102 */
1103 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
1104 fio_flags = get_fio_flags(fenc);
1105
1106# ifdef WIN3264
1107 /*
1108 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
1109 * is handled with MultiByteToWideChar().
1110 */
1111 if (fio_flags == 0)
1112 fio_flags = get_win_fio_flags(fenc);
1113# endif
1114
Bram Moolenaard0573012017-10-28 21:11:06 +02001115# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001116 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
1117 if (fio_flags == 0)
1118 fio_flags = get_mac_fio_flags(fenc);
1119# endif
1120
1121# ifdef USE_ICONV
1122 /*
1123 * Try using iconv() if we can't convert internally.
1124 */
1125 if (fio_flags == 0
1126# ifdef FEAT_EVAL
1127 && !did_iconv
1128# endif
1129 )
1130 iconv_fd = (iconv_t)my_iconv_open(
1131 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
1132# endif
1133
1134# ifdef FEAT_EVAL
1135 /*
1136 * Use the 'charconvert' expression when conversion is required
1137 * and we can't do it internally or with iconv().
1138 */
1139 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001140 && !read_fifo
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141# ifdef USE_ICONV
1142 && iconv_fd == (iconv_t)-1
1143# endif
1144 )
1145 {
1146# ifdef USE_ICONV
1147 did_iconv = FALSE;
1148# endif
1149 /* Skip conversion when it's already done (retry for wrong
1150 * "fileformat"). */
1151 if (tmpname == NULL)
1152 {
1153 tmpname = readfile_charconvert(fname, fenc, &fd);
1154 if (tmpname == NULL)
1155 {
1156 /* Conversion failed. Try another one. */
1157 advance_fenc = TRUE;
1158 if (fd < 0)
1159 {
1160 /* Re-opening the original file failed! */
1161 EMSG(_("E202: Conversion made file unreadable!"));
1162 error = TRUE;
1163 goto failed;
1164 }
1165 goto retry;
1166 }
1167 }
1168 }
1169 else
1170# endif
1171 {
1172 if (fio_flags == 0
1173# ifdef USE_ICONV
1174 && iconv_fd == (iconv_t)-1
1175# endif
1176 )
1177 {
1178 /* Conversion wanted but we can't.
1179 * Try the next conversion in 'fileencodings' */
1180 advance_fenc = TRUE;
1181 goto retry;
1182 }
1183 }
1184 }
1185
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001186 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001187 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001188 * stdin or fixed at a specific encoding. */
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001189 can_retry = (*fenc != NUL && !read_stdin && !read_fifo && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001190#endif
1191
1192 if (!skip_read)
1193 {
1194 linerest = 0;
1195 filesize = 0;
1196 skip_count = lines_to_skip;
1197 read_count = lines_to_read;
1198#ifdef FEAT_MBYTE
1199 conv_restlen = 0;
1200#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001201#ifdef FEAT_PERSISTENT_UNDO
Bram Moolenaar59f931e2010-07-24 20:27:03 +02001202 read_undo_file = (newfile && (flags & READ_KEEP_UNDO) == 0
1203 && curbuf->b_ffname != NULL
1204 && curbuf->b_p_udf
1205 && !filtering
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02001206 && !read_fifo
Bram Moolenaar59f931e2010-07-24 20:27:03 +02001207 && !read_stdin
1208 && !read_buffer);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001209 if (read_undo_file)
1210 sha256_start(&sha_ctx);
1211#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001212#ifdef FEAT_CRYPT
1213 if (curbuf->b_cryptstate != NULL)
1214 {
1215 /* Need to free the state, but keep the key, don't want to ask for
1216 * it again. */
1217 crypt_free_state(curbuf->b_cryptstate);
1218 curbuf->b_cryptstate = NULL;
1219 }
1220#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001221 }
1222
1223 while (!error && !got_int)
1224 {
1225 /*
1226 * We allocate as much space for the file as we can get, plus
1227 * space for the old line plus room for one terminating NUL.
1228 * The amount is limited by the fact that read() only can read
1229 * upto max_unsigned characters (and other things).
1230 */
Bram Moolenaara2aa31a2014-02-23 22:52:40 +01001231#if VIM_SIZEOF_INT <= 2
Bram Moolenaar071d4272004-06-13 20:20:40 +00001232 if (linerest >= 0x7ff0)
1233 {
1234 ++split;
1235 *ptr = NL; /* split line by inserting a NL */
1236 size = 1;
1237 }
1238 else
1239#endif
1240 {
1241 if (!skip_read)
1242 {
Bram Moolenaara2aa31a2014-02-23 22:52:40 +01001243#if VIM_SIZEOF_INT > 2
Bram Moolenaar311d9822007-02-27 15:48:28 +00001244# if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001245 size = SSIZE_MAX; /* use max I/O size, 52K */
1246# else
1247 size = 0x10000L; /* use buffer >= 64K */
1248# endif
1249#else
1250 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1251#endif
1252
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001253 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001254 {
1255 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1256 FALSE)) != NULL)
1257 break;
1258 }
1259 if (new_buffer == NULL)
1260 {
1261 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1262 error = TRUE;
1263 break;
1264 }
1265 if (linerest) /* copy characters from the previous buffer */
1266 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1267 vim_free(buffer);
1268 buffer = new_buffer;
1269 ptr = buffer + linerest;
1270 line_start = buffer;
1271
1272#ifdef FEAT_MBYTE
1273 /* May need room to translate into.
1274 * For iconv() we don't really know the required space, use a
1275 * factor ICONV_MULT.
1276 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1277 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1278 * become up to 4 bytes, size must be multiple of 2
1279 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1280 * multiple of 2
1281 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1282 * multiple of 4 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001283 real_size = (int)size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284# ifdef USE_ICONV
1285 if (iconv_fd != (iconv_t)-1)
1286 size = size / ICONV_MULT;
1287 else
1288# endif
1289 if (fio_flags & FIO_LATIN1)
1290 size = size / 2;
1291 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1292 size = (size * 2 / 3) & ~1;
1293 else if (fio_flags & FIO_UCS4)
1294 size = (size * 2 / 3) & ~3;
1295 else if (fio_flags == FIO_UCSBOM)
1296 size = size / ICONV_MULT; /* worst case */
1297# ifdef WIN3264
1298 else if (fio_flags & FIO_CODEPAGE)
1299 size = size / ICONV_MULT; /* also worst case */
1300# endif
Bram Moolenaard0573012017-10-28 21:11:06 +02001301# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302 else if (fio_flags & FIO_MACROMAN)
1303 size = size / ICONV_MULT; /* also worst case */
1304# endif
1305#endif
1306
1307#ifdef FEAT_MBYTE
1308 if (conv_restlen > 0)
1309 {
1310 /* Insert unconverted bytes from previous line. */
1311 mch_memmove(ptr, conv_rest, conv_restlen);
1312 ptr += conv_restlen;
1313 size -= conv_restlen;
1314 }
1315#endif
1316
1317 if (read_buffer)
1318 {
1319 /*
1320 * Read bytes from curbuf. Used for converting text read
1321 * from stdin.
1322 */
1323 if (read_buf_lnum > from)
1324 size = 0;
1325 else
1326 {
1327 int n, ni;
1328 long tlen;
1329
1330 tlen = 0;
1331 for (;;)
1332 {
1333 p = ml_get(read_buf_lnum) + read_buf_col;
1334 n = (int)STRLEN(p);
1335 if ((int)tlen + n + 1 > size)
1336 {
1337 /* Filled up to "size", append partial line.
1338 * Change NL to NUL to reverse the effect done
1339 * below. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001340 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001341 for (ni = 0; ni < n; ++ni)
1342 {
1343 if (p[ni] == NL)
1344 ptr[tlen++] = NUL;
1345 else
1346 ptr[tlen++] = p[ni];
1347 }
1348 read_buf_col += n;
1349 break;
1350 }
1351 else
1352 {
1353 /* Append whole line and new-line. Change NL
1354 * to NUL to reverse the effect done below. */
1355 for (ni = 0; ni < n; ++ni)
1356 {
1357 if (p[ni] == NL)
1358 ptr[tlen++] = NUL;
1359 else
1360 ptr[tlen++] = p[ni];
1361 }
1362 ptr[tlen++] = NL;
1363 read_buf_col = 0;
1364 if (++read_buf_lnum > from)
1365 {
1366 /* When the last line didn't have an
1367 * end-of-line don't add it now either. */
1368 if (!curbuf->b_p_eol)
1369 --tlen;
1370 size = tlen;
1371 break;
1372 }
1373 }
1374 }
1375 }
1376 }
1377 else
1378 {
1379 /*
1380 * Read bytes from the file.
1381 */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01001382 size = read_eintr(fd, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001383 }
1384
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001385#ifdef FEAT_CRYPT
1386 /*
1387 * At start of file: Check for magic number of encryption.
1388 */
1389 if (filesize == 0 && size > 0)
1390 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
1391 &filesize, newfile, sfname,
1392 &did_ask_for_key);
1393 /*
1394 * Decrypt the read bytes. This is done before checking for
1395 * EOF because the crypt layer may be buffering.
1396 */
Bram Moolenaar829aa642017-08-23 22:32:35 +02001397 if (cryptkey != NULL && curbuf->b_cryptstate != NULL
1398 && size > 0)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001399 {
1400 if (crypt_works_inplace(curbuf->b_cryptstate))
1401 {
1402 crypt_decode_inplace(curbuf->b_cryptstate, ptr, size);
1403 }
1404 else
1405 {
1406 char_u *newptr = NULL;
1407 int decrypted_size;
1408
1409 decrypted_size = crypt_decode_alloc(
1410 curbuf->b_cryptstate, ptr, size, &newptr);
1411
1412 /* If the crypt layer is buffering, not producing
1413 * anything yet, need to read more. */
1414 if (size > 0 && decrypted_size == 0)
1415 continue;
1416
1417 if (linerest == 0)
1418 {
1419 /* Simple case: reuse returned buffer (may be
1420 * NULL, checked later). */
1421 new_buffer = newptr;
1422 }
1423 else
1424 {
1425 long_u new_size;
1426
1427 /* Need new buffer to add bytes carried over. */
1428 new_size = (long_u)(decrypted_size + linerest + 1);
1429 new_buffer = lalloc(new_size, FALSE);
1430 if (new_buffer == NULL)
1431 {
1432 do_outofmem_msg(new_size);
1433 error = TRUE;
1434 break;
1435 }
1436
1437 mch_memmove(new_buffer, buffer, linerest);
1438 if (newptr != NULL)
1439 mch_memmove(new_buffer + linerest, newptr,
1440 decrypted_size);
1441 }
1442
1443 if (new_buffer != NULL)
1444 {
1445 vim_free(buffer);
1446 buffer = new_buffer;
1447 new_buffer = NULL;
1448 line_start = buffer;
1449 ptr = buffer + linerest;
1450 }
1451 size = decrypted_size;
1452 }
1453 }
1454#endif
1455
Bram Moolenaar071d4272004-06-13 20:20:40 +00001456 if (size <= 0)
1457 {
1458 if (size < 0) /* read error */
1459 error = TRUE;
1460#ifdef FEAT_MBYTE
1461 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001462 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001463 /*
1464 * Reached end-of-file but some trailing bytes could
1465 * not be converted. Truncated file?
1466 */
1467
1468 /* When we did a conversion report an error. */
1469 if (fio_flags != 0
1470# ifdef USE_ICONV
1471 || iconv_fd != (iconv_t)-1
1472# endif
1473 )
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001474 {
Bram Moolenaare8d95302013-04-24 16:34:02 +02001475 if (can_retry)
1476 goto rewind_retry;
Bram Moolenaarf453d352008-06-04 17:37:34 +00001477 if (conv_error == 0)
1478 conv_error = curbuf->b_ml.ml_line_count
1479 - linecnt + 1;
1480 }
1481 /* Remember the first linenr with an illegal byte */
1482 else if (illegal_byte == 0)
1483 illegal_byte = curbuf->b_ml.ml_line_count
1484 - linecnt + 1;
1485 if (bad_char_behavior == BAD_DROP)
1486 {
1487 *(ptr - conv_restlen) = NUL;
1488 conv_restlen = 0;
1489 }
1490 else
1491 {
1492 /* Replace the trailing bytes with the replacement
1493 * character if we were converting; if we weren't,
1494 * leave the UTF8 checking code to do it, as it
1495 * works slightly differently. */
1496 if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
1497# ifdef USE_ICONV
1498 || iconv_fd != (iconv_t)-1
1499# endif
1500 ))
1501 {
1502 while (conv_restlen > 0)
1503 {
1504 *(--ptr) = bad_char_behavior;
1505 --conv_restlen;
1506 }
1507 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001508 fio_flags = 0; /* don't convert this */
Bram Moolenaarb21e5842006-04-16 18:30:08 +00001509# ifdef USE_ICONV
1510 if (iconv_fd != (iconv_t)-1)
1511 {
1512 iconv_close(iconv_fd);
1513 iconv_fd = (iconv_t)-1;
1514 }
1515# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001516 }
1517 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001518#endif
1519 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001520 }
1521 skip_read = FALSE;
1522
1523#ifdef FEAT_MBYTE
1524 /*
1525 * At start of file (or after crypt magic number): Check for BOM.
1526 * Also check for a BOM for other Unicode encodings, but not after
1527 * converting with 'charconvert' or when a BOM has already been
1528 * found.
1529 */
1530 if ((filesize == 0
1531# ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02001532 || (cryptkey != NULL
1533 && filesize == crypt_get_header_len(
1534 crypt_get_method_nr(curbuf)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001535# endif
1536 )
1537 && (fio_flags == FIO_UCSBOM
1538 || (!curbuf->b_p_bomb
1539 && tmpname == NULL
1540 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1541 {
1542 char_u *ccname;
1543 int blen;
1544
1545 /* no BOM detection in a short file or in binary mode */
1546 if (size < 2 || curbuf->b_p_bin)
1547 ccname = NULL;
1548 else
1549 ccname = check_for_bom(ptr, size, &blen,
1550 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1551 if (ccname != NULL)
1552 {
1553 /* Remove BOM from the text */
1554 filesize += blen;
1555 size -= blen;
1556 mch_memmove(ptr, ptr + blen, (size_t)size);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001557 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001558 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001559 curbuf->b_p_bomb = TRUE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001560 curbuf->b_start_bomb = TRUE;
1561 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001562 }
1563
1564 if (fio_flags == FIO_UCSBOM)
1565 {
1566 if (ccname == NULL)
1567 {
1568 /* No BOM detected: retry with next encoding. */
1569 advance_fenc = TRUE;
1570 }
1571 else
1572 {
1573 /* BOM detected: set "fenc" and jump back */
1574 if (fenc_alloced)
1575 vim_free(fenc);
1576 fenc = ccname;
1577 fenc_alloced = FALSE;
1578 }
1579 /* retry reading without getting new bytes or rewinding */
1580 skip_read = TRUE;
1581 goto retry;
1582 }
1583 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00001584
1585 /* Include not converted bytes. */
1586 ptr -= conv_restlen;
1587 size += conv_restlen;
1588 conv_restlen = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001589#endif
1590 /*
1591 * Break here for a read error or end-of-file.
1592 */
1593 if (size <= 0)
1594 break;
1595
1596#ifdef FEAT_MBYTE
1597
Bram Moolenaar071d4272004-06-13 20:20:40 +00001598# ifdef USE_ICONV
1599 if (iconv_fd != (iconv_t)-1)
1600 {
1601 /*
1602 * Attempt conversion of the read bytes to 'encoding' using
1603 * iconv().
1604 */
1605 const char *fromp;
1606 char *top;
1607 size_t from_size;
1608 size_t to_size;
1609
1610 fromp = (char *)ptr;
1611 from_size = size;
1612 ptr += size;
1613 top = (char *)ptr;
1614 to_size = real_size - size;
1615
1616 /*
1617 * If there is conversion error or not enough room try using
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001618 * another conversion. Except for when there is no
1619 * alternative (help files).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001620 */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001621 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1622 &top, &to_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001623 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1624 || from_size > CONV_RESTLEN)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001625 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001626 if (can_retry)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001627 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001628 if (conv_error == 0)
1629 conv_error = readfile_linenr(linecnt,
1630 ptr, (char_u *)top);
Bram Moolenaar42eeac32005-06-29 22:40:58 +00001631
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001632 /* Deal with a bad byte and continue with the next. */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001633 ++fromp;
1634 --from_size;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001635 if (bad_char_behavior == BAD_KEEP)
1636 {
1637 *top++ = *(fromp - 1);
1638 --to_size;
1639 }
1640 else if (bad_char_behavior != BAD_DROP)
1641 {
1642 *top++ = bad_char_behavior;
1643 --to_size;
1644 }
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001645 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646
1647 if (from_size > 0)
1648 {
1649 /* Some remaining characters, keep them for the next
1650 * round. */
1651 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1652 conv_restlen = (int)from_size;
1653 }
1654
1655 /* move the linerest to before the converted characters */
1656 line_start = ptr - linerest;
1657 mch_memmove(line_start, buffer, (size_t)linerest);
1658 size = (long)((char_u *)top - ptr);
1659 }
1660# endif
1661
1662# ifdef WIN3264
1663 if (fio_flags & FIO_CODEPAGE)
1664 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001665 char_u *src, *dst;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001666 WCHAR ucs2buf[3];
1667 int ucs2len;
1668 int codepage = FIO_GET_CP(fio_flags);
1669 int bytelen;
1670 int found_bad;
1671 char replstr[2];
1672
Bram Moolenaar071d4272004-06-13 20:20:40 +00001673 /*
1674 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001675 * a codepage, using standard MS-Windows functions. This
1676 * requires two steps:
1677 * 1. convert from 'fileencoding' to ucs-2
1678 * 2. convert from ucs-2 to 'encoding'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001679 *
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001680 * Because there may be illegal bytes AND an incomplete byte
1681 * sequence at the end, we may have to do the conversion one
1682 * character at a time to get it right.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001683 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001684
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001685 /* Replacement string for WideCharToMultiByte(). */
1686 if (bad_char_behavior > 0)
1687 replstr[0] = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001688 else
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001689 replstr[0] = '?';
1690 replstr[1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001691
1692 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001693 * Move the bytes to the end of the buffer, so that we have
1694 * room to put the result at the start.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001695 */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001696 src = ptr + real_size - size;
1697 mch_memmove(src, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001698
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001699 /*
1700 * Do the conversion.
1701 */
1702 dst = ptr;
1703 size = size;
1704 while (size > 0)
1705 {
1706 found_bad = FALSE;
1707
1708# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1709 if (codepage == CP_UTF8)
1710 {
1711 /* Handle CP_UTF8 input ourselves to be able to handle
1712 * trailing bytes properly.
1713 * Get one UTF-8 character from src. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001714 bytelen = (int)utf_ptr2len_len(src, size);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001715 if (bytelen > size)
1716 {
1717 /* Only got some bytes of a character. Normally
1718 * it's put in "conv_rest", but if it's too long
1719 * deal with it as if they were illegal bytes. */
1720 if (bytelen <= CONV_RESTLEN)
1721 break;
1722
1723 /* weird overlong byte sequence */
1724 bytelen = size;
1725 found_bad = TRUE;
1726 }
1727 else
1728 {
Bram Moolenaarc01140a2006-03-24 22:21:52 +00001729 int u8c = utf_ptr2char(src);
1730
Bram Moolenaar86e01082005-12-29 22:45:34 +00001731 if (u8c > 0xffff || (*src >= 0x80 && bytelen == 1))
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001732 found_bad = TRUE;
1733 ucs2buf[0] = u8c;
1734 ucs2len = 1;
1735 }
1736 }
1737 else
1738# endif
1739 {
1740 /* We don't know how long the byte sequence is, try
1741 * from one to three bytes. */
1742 for (bytelen = 1; bytelen <= size && bytelen <= 3;
1743 ++bytelen)
1744 {
1745 ucs2len = MultiByteToWideChar(codepage,
1746 MB_ERR_INVALID_CHARS,
1747 (LPCSTR)src, bytelen,
1748 ucs2buf, 3);
1749 if (ucs2len > 0)
1750 break;
1751 }
1752 if (ucs2len == 0)
1753 {
1754 /* If we have only one byte then it's probably an
1755 * incomplete byte sequence. Otherwise discard
1756 * one byte as a bad character. */
1757 if (size == 1)
1758 break;
1759 found_bad = TRUE;
1760 bytelen = 1;
1761 }
1762 }
1763
1764 if (!found_bad)
1765 {
1766 int i;
1767
1768 /* Convert "ucs2buf[ucs2len]" to 'enc' in "dst". */
1769 if (enc_utf8)
1770 {
1771 /* From UCS-2 to UTF-8. Cannot fail. */
1772 for (i = 0; i < ucs2len; ++i)
1773 dst += utf_char2bytes(ucs2buf[i], dst);
1774 }
1775 else
1776 {
1777 BOOL bad = FALSE;
1778 int dstlen;
1779
1780 /* From UCS-2 to "enc_codepage". If the
1781 * conversion uses the default character "?",
1782 * the data doesn't fit in this encoding. */
1783 dstlen = WideCharToMultiByte(enc_codepage, 0,
1784 (LPCWSTR)ucs2buf, ucs2len,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001785 (LPSTR)dst, (int)(src - dst),
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001786 replstr, &bad);
1787 if (bad)
1788 found_bad = TRUE;
1789 else
1790 dst += dstlen;
1791 }
1792 }
1793
1794 if (found_bad)
1795 {
1796 /* Deal with bytes we can't convert. */
1797 if (can_retry)
1798 goto rewind_retry;
1799 if (conv_error == 0)
1800 conv_error = readfile_linenr(linecnt, ptr, dst);
1801 if (bad_char_behavior != BAD_DROP)
1802 {
1803 if (bad_char_behavior == BAD_KEEP)
1804 {
1805 mch_memmove(dst, src, bytelen);
1806 dst += bytelen;
1807 }
1808 else
1809 *dst++ = bad_char_behavior;
1810 }
1811 }
1812
1813 src += bytelen;
1814 size -= bytelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001815 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001816
1817 if (size > 0)
1818 {
1819 /* An incomplete byte sequence remaining. */
1820 mch_memmove(conv_rest, src, size);
1821 conv_restlen = size;
1822 }
1823
1824 /* The new size is equal to how much "dst" was advanced. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001825 size = (long)(dst - ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001826 }
1827 else
1828# endif
Bram Moolenaar56718732006-03-15 22:53:57 +00001829# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001830 if (fio_flags & FIO_MACROMAN)
1831 {
1832 /*
1833 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001834 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001836 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001837 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001838 }
1839 else
1840# endif
1841 if (fio_flags != 0)
1842 {
1843 int u8c;
1844 char_u *dest;
1845 char_u *tail = NULL;
1846
1847 /*
1848 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1849 * "enc_utf8" not set: Convert Unicode to Latin1.
1850 * Go from end to start through the buffer, because the number
1851 * of bytes may increase.
1852 * "dest" points to after where the UTF-8 bytes go, "p" points
1853 * to after the next character to convert.
1854 */
1855 dest = ptr + real_size;
1856 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1857 {
1858 p = ptr + size;
1859 if (fio_flags == FIO_UTF8)
1860 {
1861 /* Check for a trailing incomplete UTF-8 sequence */
1862 tail = ptr + size - 1;
1863 while (tail > ptr && (*tail & 0xc0) == 0x80)
1864 --tail;
1865 if (tail + utf_byte2len(*tail) <= ptr + size)
1866 tail = NULL;
1867 else
1868 p = tail;
1869 }
1870 }
1871 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1872 {
1873 /* Check for a trailing byte */
1874 p = ptr + (size & ~1);
1875 if (size & 1)
1876 tail = p;
1877 if ((fio_flags & FIO_UTF16) && p > ptr)
1878 {
1879 /* Check for a trailing leading word */
1880 if (fio_flags & FIO_ENDIAN_L)
1881 {
1882 u8c = (*--p << 8);
1883 u8c += *--p;
1884 }
1885 else
1886 {
1887 u8c = *--p;
1888 u8c += (*--p << 8);
1889 }
1890 if (u8c >= 0xd800 && u8c <= 0xdbff)
1891 tail = p;
1892 else
1893 p += 2;
1894 }
1895 }
1896 else /* FIO_UCS4 */
1897 {
1898 /* Check for trailing 1, 2 or 3 bytes */
1899 p = ptr + (size & ~3);
1900 if (size & 3)
1901 tail = p;
1902 }
1903
1904 /* If there is a trailing incomplete sequence move it to
1905 * conv_rest[]. */
1906 if (tail != NULL)
1907 {
1908 conv_restlen = (int)((ptr + size) - tail);
1909 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1910 size -= conv_restlen;
1911 }
1912
1913
1914 while (p > ptr)
1915 {
1916 if (fio_flags & FIO_LATIN1)
1917 u8c = *--p;
1918 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1919 {
1920 if (fio_flags & FIO_ENDIAN_L)
1921 {
1922 u8c = (*--p << 8);
1923 u8c += *--p;
1924 }
1925 else
1926 {
1927 u8c = *--p;
1928 u8c += (*--p << 8);
1929 }
1930 if ((fio_flags & FIO_UTF16)
1931 && u8c >= 0xdc00 && u8c <= 0xdfff)
1932 {
1933 int u16c;
1934
1935 if (p == ptr)
1936 {
1937 /* Missing leading word. */
1938 if (can_retry)
1939 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001940 if (conv_error == 0)
1941 conv_error = readfile_linenr(linecnt,
1942 ptr, p);
1943 if (bad_char_behavior == BAD_DROP)
1944 continue;
1945 if (bad_char_behavior != BAD_KEEP)
1946 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001947 }
1948
1949 /* found second word of double-word, get the first
1950 * word and compute the resulting character */
1951 if (fio_flags & FIO_ENDIAN_L)
1952 {
1953 u16c = (*--p << 8);
1954 u16c += *--p;
1955 }
1956 else
1957 {
1958 u16c = *--p;
1959 u16c += (*--p << 8);
1960 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001961 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1962 + (u8c & 0x3ff);
1963
Bram Moolenaar071d4272004-06-13 20:20:40 +00001964 /* Check if the word is indeed a leading word. */
1965 if (u16c < 0xd800 || u16c > 0xdbff)
1966 {
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 else if (fio_flags & FIO_UCS4)
1980 {
1981 if (fio_flags & FIO_ENDIAN_L)
1982 {
Bram Moolenaardc1c9812017-10-27 22:15:24 +02001983 u8c = (unsigned)*--p << 24;
1984 u8c += (unsigned)*--p << 16;
1985 u8c += (unsigned)*--p << 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001986 u8c += *--p;
1987 }
1988 else /* big endian */
1989 {
1990 u8c = *--p;
Bram Moolenaardc1c9812017-10-27 22:15:24 +02001991 u8c += (unsigned)*--p << 8;
1992 u8c += (unsigned)*--p << 16;
1993 u8c += (unsigned)*--p << 24;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001994 }
1995 }
1996 else /* UTF-8 */
1997 {
1998 if (*--p < 0x80)
1999 u8c = *p;
2000 else
2001 {
2002 len = utf_head_off(ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002003 p -= len;
2004 u8c = utf_ptr2char(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002005 if (len == 0)
2006 {
2007 /* Not a valid UTF-8 character, retry with
2008 * another fenc when possible, otherwise just
2009 * report the error. */
2010 if (can_retry)
2011 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002012 if (conv_error == 0)
2013 conv_error = readfile_linenr(linecnt,
2014 ptr, p);
2015 if (bad_char_behavior == BAD_DROP)
2016 continue;
2017 if (bad_char_behavior != BAD_KEEP)
2018 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002019 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002020 }
2021 }
2022 if (enc_utf8) /* produce UTF-8 */
2023 {
2024 dest -= utf_char2len(u8c);
2025 (void)utf_char2bytes(u8c, dest);
2026 }
2027 else /* produce Latin1 */
2028 {
2029 --dest;
2030 if (u8c >= 0x100)
2031 {
2032 /* character doesn't fit in latin1, retry with
2033 * another fenc when possible, otherwise just
2034 * report the error. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002035 if (can_retry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002036 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002037 if (conv_error == 0)
2038 conv_error = readfile_linenr(linecnt, ptr, p);
2039 if (bad_char_behavior == BAD_DROP)
2040 ++dest;
2041 else if (bad_char_behavior == BAD_KEEP)
2042 *dest = u8c;
2043 else if (eap != NULL && eap->bad_char != 0)
2044 *dest = bad_char_behavior;
2045 else
2046 *dest = 0xBF;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002047 }
2048 else
2049 *dest = u8c;
2050 }
2051 }
2052
2053 /* move the linerest to before the converted characters */
2054 line_start = dest - linerest;
2055 mch_memmove(line_start, buffer, (size_t)linerest);
2056 size = (long)((ptr + real_size) - dest);
2057 ptr = dest;
2058 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002059 else if (enc_utf8 && !curbuf->b_p_bin)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002060 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002061 int incomplete_tail = FALSE;
2062
2063 /* Reading UTF-8: Check if the bytes are valid UTF-8. */
2064 for (p = ptr; ; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002065 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002066 int todo = (int)((ptr + size) - p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002067 int l;
2068
2069 if (todo <= 0)
2070 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002071 if (*p >= 0x80)
2072 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002073 /* A length of 1 means it's an illegal byte. Accept
2074 * an incomplete character at the end though, the next
2075 * read() will get the next bytes, we'll check it
2076 * then. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002077 l = utf_ptr2len_len(p, todo);
Bram Moolenaarf453d352008-06-04 17:37:34 +00002078 if (l > todo && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002079 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002080 /* Avoid retrying with a different encoding when
2081 * a truncated file is more likely, or attempting
2082 * to read the rest of an incomplete sequence when
2083 * we have already done so. */
2084 if (p > ptr || filesize > 0)
2085 incomplete_tail = TRUE;
2086 /* Incomplete byte sequence, move it to conv_rest[]
2087 * and try to read the rest of it, unless we've
2088 * already done so. */
2089 if (p > ptr)
2090 {
2091 conv_restlen = todo;
2092 mch_memmove(conv_rest, p, conv_restlen);
2093 size -= conv_restlen;
2094 break;
2095 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002096 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002097 if (l == 1 || l > todo)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002098 {
2099 /* Illegal byte. If we can try another encoding
Bram Moolenaarf453d352008-06-04 17:37:34 +00002100 * do that, unless at EOF where a truncated
2101 * file is more likely than a conversion error. */
2102 if (can_retry && !incomplete_tail)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002103 break;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002104# ifdef USE_ICONV
2105 /* When we did a conversion report an error. */
2106 if (iconv_fd != (iconv_t)-1 && conv_error == 0)
2107 conv_error = readfile_linenr(linecnt, ptr, p);
2108# endif
Bram Moolenaarf453d352008-06-04 17:37:34 +00002109 /* Remember the first linenr with an illegal byte */
2110 if (conv_error == 0 && illegal_byte == 0)
2111 illegal_byte = readfile_linenr(linecnt, ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002112
2113 /* Drop, keep or replace the bad byte. */
2114 if (bad_char_behavior == BAD_DROP)
2115 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002116 mch_memmove(p, p + 1, todo - 1);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002117 --p;
2118 --size;
2119 }
2120 else if (bad_char_behavior != BAD_KEEP)
2121 *p = bad_char_behavior;
2122 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002123 else
2124 p += l - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002125 }
2126 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002127 if (p < ptr + size && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002128 {
2129 /* Detected a UTF-8 error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002130rewind_retry:
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002131 /* Retry reading with another conversion. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002132# if defined(FEAT_EVAL) && defined(USE_ICONV)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002133 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
2134 /* iconv() failed, try 'charconvert' */
2135 did_iconv = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002136 else
2137# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002138 /* use next item from 'fileencodings' */
2139 advance_fenc = TRUE;
2140 file_rewind = TRUE;
2141 goto retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002142 }
2143 }
2144#endif
2145
2146 /* count the number of characters (after conversion!) */
2147 filesize += size;
2148
2149 /*
2150 * when reading the first part of a file: guess EOL type
2151 */
2152 if (fileformat == EOL_UNKNOWN)
2153 {
2154 /* First try finding a NL, for Dos and Unix */
2155 if (try_dos || try_unix)
2156 {
Bram Moolenaarc6b72172015-02-27 17:48:09 +01002157 /* Reset the carriage return counter. */
2158 if (try_mac)
2159 try_mac = 1;
2160
Bram Moolenaar071d4272004-06-13 20:20:40 +00002161 for (p = ptr; p < ptr + size; ++p)
2162 {
2163 if (*p == NL)
2164 {
2165 if (!try_unix
2166 || (try_dos && p > ptr && p[-1] == CAR))
2167 fileformat = EOL_DOS;
2168 else
2169 fileformat = EOL_UNIX;
2170 break;
2171 }
Bram Moolenaar05eb6122015-02-17 14:15:19 +01002172 else if (*p == CAR && try_mac)
2173 try_mac++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002174 }
2175
2176 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
2177 if (fileformat == EOL_UNIX && try_mac)
2178 {
2179 /* Need to reset the counters when retrying fenc. */
2180 try_mac = 1;
2181 try_unix = 1;
2182 for (; p >= ptr && *p != CAR; p--)
2183 ;
2184 if (p >= ptr)
2185 {
2186 for (p = ptr; p < ptr + size; ++p)
2187 {
2188 if (*p == NL)
2189 try_unix++;
2190 else if (*p == CAR)
2191 try_mac++;
2192 }
2193 if (try_mac > try_unix)
2194 fileformat = EOL_MAC;
2195 }
2196 }
Bram Moolenaar05eb6122015-02-17 14:15:19 +01002197 else if (fileformat == EOL_UNKNOWN && try_mac == 1)
2198 /* Looking for CR but found no end-of-line markers at
2199 * all: use the default format. */
2200 fileformat = default_fileformat();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002201 }
2202
2203 /* No NL found: may use Mac format */
2204 if (fileformat == EOL_UNKNOWN && try_mac)
2205 fileformat = EOL_MAC;
2206
2207 /* Still nothing found? Use first format in 'ffs' */
2208 if (fileformat == EOL_UNKNOWN)
2209 fileformat = default_fileformat();
2210
2211 /* if editing a new file: may set p_tx and p_ff */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002212 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002213 set_fileformat(fileformat, OPT_LOCAL);
2214 }
2215 }
2216
2217 /*
2218 * This loop is executed once for every character read.
2219 * Keep it fast!
2220 */
2221 if (fileformat == EOL_MAC)
2222 {
2223 --ptr;
2224 while (++ptr, --size >= 0)
2225 {
2226 /* catch most common case first */
2227 if ((c = *ptr) != NUL && c != CAR && c != NL)
2228 continue;
2229 if (c == NUL)
2230 *ptr = NL; /* NULs are replaced by newlines! */
2231 else if (c == NL)
2232 *ptr = CAR; /* NLs are replaced by CRs! */
2233 else
2234 {
2235 if (skip_count == 0)
2236 {
2237 *ptr = NUL; /* end of line */
2238 len = (colnr_T) (ptr - line_start + 1);
2239 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2240 {
2241 error = TRUE;
2242 break;
2243 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002244#ifdef FEAT_PERSISTENT_UNDO
2245 if (read_undo_file)
2246 sha256_update(&sha_ctx, line_start, len);
2247#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002248 ++lnum;
2249 if (--read_count == 0)
2250 {
2251 error = TRUE; /* break loop */
2252 line_start = ptr; /* nothing left to write */
2253 break;
2254 }
2255 }
2256 else
2257 --skip_count;
2258 line_start = ptr + 1;
2259 }
2260 }
2261 }
2262 else
2263 {
2264 --ptr;
2265 while (++ptr, --size >= 0)
2266 {
2267 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2268 continue;
2269 if (c == NUL)
2270 *ptr = NL; /* NULs are replaced by newlines! */
2271 else
2272 {
2273 if (skip_count == 0)
2274 {
2275 *ptr = NUL; /* end of line */
2276 len = (colnr_T)(ptr - line_start + 1);
2277 if (fileformat == EOL_DOS)
2278 {
Bram Moolenaar2aa5f692017-01-24 15:46:48 +01002279 if (ptr > line_start && ptr[-1] == CAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002280 {
Bram Moolenaar2aa5f692017-01-24 15:46:48 +01002281 /* remove CR before NL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 ptr[-1] = NUL;
2283 --len;
2284 }
2285 /*
2286 * Reading in Dos format, but no CR-LF found!
2287 * When 'fileformats' includes "unix", delete all
2288 * the lines read so far and start all over again.
2289 * Otherwise give an error message later.
2290 */
2291 else if (ff_error != EOL_DOS)
2292 {
2293 if ( try_unix
2294 && !read_stdin
2295 && (read_buffer
Bram Moolenaar8767f522016-07-01 17:17:39 +02002296 || vim_lseek(fd, (off_T)0L, SEEK_SET)
2297 == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002298 {
2299 fileformat = EOL_UNIX;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002300 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002301 set_fileformat(EOL_UNIX, OPT_LOCAL);
2302 file_rewind = TRUE;
2303 keep_fileformat = TRUE;
2304 goto retry;
2305 }
2306 ff_error = EOL_DOS;
2307 }
2308 }
2309 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2310 {
2311 error = TRUE;
2312 break;
2313 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002314#ifdef FEAT_PERSISTENT_UNDO
2315 if (read_undo_file)
2316 sha256_update(&sha_ctx, line_start, len);
2317#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002318 ++lnum;
2319 if (--read_count == 0)
2320 {
2321 error = TRUE; /* break loop */
2322 line_start = ptr; /* nothing left to write */
2323 break;
2324 }
2325 }
2326 else
2327 --skip_count;
2328 line_start = ptr + 1;
2329 }
2330 }
2331 }
2332 linerest = (long)(ptr - line_start);
2333 ui_breakcheck();
2334 }
2335
2336failed:
2337 /* not an error, max. number of lines reached */
2338 if (error && read_count == 0)
2339 error = FALSE;
2340
2341 /*
2342 * If we get EOF in the middle of a line, note the fact and
2343 * complete the line ourselves.
2344 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2345 */
2346 if (!error
2347 && !got_int
2348 && linerest != 0
2349 && !(!curbuf->b_p_bin
2350 && fileformat == EOL_DOS
2351 && *line_start == Ctrl_Z
2352 && ptr == line_start + 1))
2353 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002354 /* remember for when writing */
2355 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002356 curbuf->b_p_eol = FALSE;
2357 *ptr = NUL;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002358 len = (colnr_T)(ptr - line_start + 1);
2359 if (ml_append(lnum, line_start, len, newfile) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002360 error = TRUE;
2361 else
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002362 {
2363#ifdef FEAT_PERSISTENT_UNDO
2364 if (read_undo_file)
2365 sha256_update(&sha_ctx, line_start, len);
2366#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002367 read_no_eol_lnum = ++lnum;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002368 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002369 }
2370
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002371 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002372 save_file_ff(curbuf); /* remember the current file format */
2373
2374#ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002375 if (curbuf->b_cryptstate != NULL)
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002376 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002377 crypt_free_state(curbuf->b_cryptstate);
2378 curbuf->b_cryptstate = NULL;
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002379 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002380 if (cryptkey != NULL && cryptkey != curbuf->b_p_key)
2381 crypt_free_key(cryptkey);
2382 /* Don't set cryptkey to NULL, it's used below as a flag that
2383 * encryption was used. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002384#endif
2385
2386#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002387 /* If editing a new file: set 'fenc' for the current buffer.
2388 * Also for ":read ++edit file". */
2389 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002390 set_string_option_direct((char_u *)"fenc", -1, fenc,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002391 OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002392 if (fenc_alloced)
2393 vim_free(fenc);
2394# ifdef USE_ICONV
2395 if (iconv_fd != (iconv_t)-1)
2396 {
2397 iconv_close(iconv_fd);
2398 iconv_fd = (iconv_t)-1;
2399 }
2400# endif
2401#endif
2402
2403 if (!read_buffer && !read_stdin)
2404 close(fd); /* errors are ignored */
Bram Moolenaarf05da212009-11-17 16:13:15 +00002405#ifdef HAVE_FD_CLOEXEC
2406 else
2407 {
2408 int fdflags = fcntl(fd, F_GETFD);
2409 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +01002410 (void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
Bram Moolenaarf05da212009-11-17 16:13:15 +00002411 }
2412#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002413 vim_free(buffer);
2414
2415#ifdef HAVE_DUP
2416 if (read_stdin)
2417 {
2418 /* Use stderr for stdin, makes shell commands work. */
2419 close(0);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00002420 ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002421 }
2422#endif
2423
2424#ifdef FEAT_MBYTE
2425 if (tmpname != NULL)
2426 {
2427 mch_remove(tmpname); /* delete converted file */
2428 vim_free(tmpname);
2429 }
2430#endif
2431 --no_wait_return; /* may wait for return now */
2432
2433 /*
2434 * In recovery mode everything but autocommands is skipped.
2435 */
2436 if (!recoverymode)
2437 {
2438 /* need to delete the last line, which comes from the empty buffer */
2439 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2440 {
2441#ifdef FEAT_NETBEANS_INTG
2442 netbeansFireChanges = 0;
2443#endif
2444 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2445#ifdef FEAT_NETBEANS_INTG
2446 netbeansFireChanges = 1;
2447#endif
2448 --linecnt;
2449 }
2450 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2451 if (filesize == 0)
2452 linecnt = 0;
2453 if (newfile || read_buffer)
Bram Moolenaar7263a772007-05-10 17:35:54 +00002454 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002455 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar7263a772007-05-10 17:35:54 +00002456#ifdef FEAT_DIFF
2457 /* After reading the text into the buffer the diff info needs to
2458 * be updated. */
2459 diff_invalidate(curbuf);
2460#endif
2461#ifdef FEAT_FOLDING
2462 /* All folds in the window are invalid now. Mark them for update
2463 * before triggering autocommands. */
2464 foldUpdateAll(curwin);
2465#endif
2466 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002467 else if (linecnt) /* appended at least one line */
2468 appended_lines_mark(from, linecnt);
2469
Bram Moolenaar071d4272004-06-13 20:20:40 +00002470#ifndef ALWAYS_USE_GUI
2471 /*
2472 * If we were reading from the same terminal as where messages go,
2473 * the screen will have been messed up.
2474 * Switch on raw mode now and clear the screen.
2475 */
2476 if (read_stdin)
2477 {
2478 settmode(TMODE_RAW); /* set to raw mode */
2479 starttermcap();
2480 screenclear();
2481 }
2482#endif
2483
2484 if (got_int)
2485 {
2486 if (!(flags & READ_DUMMY))
2487 {
2488 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2489 if (newfile)
2490 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2491 }
2492 msg_scroll = msg_save;
2493#ifdef FEAT_VIMINFO
2494 check_marks_read();
2495#endif
2496 return OK; /* an interrupt isn't really an error */
2497 }
2498
2499 if (!filtering && !(flags & READ_DUMMY))
2500 {
2501 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2502 c = FALSE;
2503
2504#ifdef UNIX
2505# ifdef S_ISFIFO
2506 if (S_ISFIFO(perm)) /* fifo or socket */
2507 {
2508 STRCAT(IObuff, _("[fifo/socket]"));
2509 c = TRUE;
2510 }
2511# else
2512# ifdef S_IFIFO
2513 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2514 {
2515 STRCAT(IObuff, _("[fifo]"));
2516 c = TRUE;
2517 }
2518# endif
2519# ifdef S_IFSOCK
2520 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2521 {
2522 STRCAT(IObuff, _("[socket]"));
2523 c = TRUE;
2524 }
2525# endif
2526# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002527# ifdef OPEN_CHR_FILES
2528 if (S_ISCHR(perm)) /* or character special */
2529 {
2530 STRCAT(IObuff, _("[character special]"));
2531 c = TRUE;
2532 }
2533# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002534#endif
2535 if (curbuf->b_p_ro)
2536 {
2537 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2538 c = TRUE;
2539 }
2540 if (read_no_eol_lnum)
2541 {
2542 msg_add_eol();
2543 c = TRUE;
2544 }
2545 if (ff_error == EOL_DOS)
2546 {
2547 STRCAT(IObuff, _("[CR missing]"));
2548 c = TRUE;
2549 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002550 if (split)
2551 {
2552 STRCAT(IObuff, _("[long lines split]"));
2553 c = TRUE;
2554 }
2555#ifdef FEAT_MBYTE
2556 if (notconverted)
2557 {
2558 STRCAT(IObuff, _("[NOT converted]"));
2559 c = TRUE;
2560 }
2561 else if (converted)
2562 {
2563 STRCAT(IObuff, _("[converted]"));
2564 c = TRUE;
2565 }
2566#endif
2567#ifdef FEAT_CRYPT
2568 if (cryptkey != NULL)
2569 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002570 crypt_append_msg(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571 c = TRUE;
2572 }
2573#endif
2574#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002575 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002576 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002577 sprintf((char *)IObuff + STRLEN(IObuff),
2578 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002579 c = TRUE;
2580 }
2581 else if (illegal_byte > 0)
2582 {
2583 sprintf((char *)IObuff + STRLEN(IObuff),
2584 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2585 c = TRUE;
2586 }
2587 else
2588#endif
2589 if (error)
2590 {
2591 STRCAT(IObuff, _("[READ ERRORS]"));
2592 c = TRUE;
2593 }
2594 if (msg_add_fileformat(fileformat))
2595 c = TRUE;
2596#ifdef FEAT_CRYPT
2597 if (cryptkey != NULL)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002598 msg_add_lines(c, (long)linecnt, filesize
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002599 - crypt_get_header_len(crypt_get_method_nr(curbuf)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 else
2601#endif
2602 msg_add_lines(c, (long)linecnt, filesize);
2603
Bram Moolenaard23a8232018-02-10 18:45:26 +01002604 VIM_CLEAR(keep_msg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002605 msg_scrolled_ign = TRUE;
2606#ifdef ALWAYS_USE_GUI
2607 /* Don't show the message when reading stdin, it would end up in a
2608 * message box (which might be shown when exiting!) */
2609 if (read_stdin || read_buffer)
2610 p = msg_may_trunc(FALSE, IObuff);
2611 else
2612#endif
2613 p = msg_trunc_attr(IObuff, FALSE, 0);
2614 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002615 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002616 /* Need to repeat the message after redrawing when:
2617 * - When reading from stdin (the screen will be cleared next).
2618 * - When restart_edit is set (otherwise there will be a delay
2619 * before redrawing).
2620 * - When the screen was scrolled but there is no wait-return
2621 * prompt. */
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002622 set_keep_msg(p, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002623 msg_scrolled_ign = FALSE;
2624 }
2625
2626 /* with errors writing the file requires ":w!" */
2627 if (newfile && (error
2628#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002629 || conv_error != 0
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002630 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631#endif
2632 ))
2633 curbuf->b_p_ro = TRUE;
2634
2635 u_clearline(); /* cannot use "U" command after adding lines */
2636
2637 /*
2638 * In Ex mode: cursor at last new line.
2639 * Otherwise: cursor at first new line.
2640 */
2641 if (exmode_active)
2642 curwin->w_cursor.lnum = from + linecnt;
2643 else
2644 curwin->w_cursor.lnum = from + 1;
2645 check_cursor_lnum();
2646 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2647
2648 /*
2649 * Set '[ and '] marks to the newly read lines.
2650 */
2651 curbuf->b_op_start.lnum = from + 1;
2652 curbuf->b_op_start.col = 0;
2653 curbuf->b_op_end.lnum = from + linecnt;
2654 curbuf->b_op_end.col = 0;
Bram Moolenaar03f48552006-02-28 23:52:23 +00002655
2656#ifdef WIN32
2657 /*
2658 * Work around a weird problem: When a file has two links (only
2659 * possible on NTFS) and we write through one link, then stat() it
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00002660 * through the other link, the timestamp information may be wrong.
Bram Moolenaar03f48552006-02-28 23:52:23 +00002661 * It's correct again after reading the file, thus reset the timestamp
2662 * here.
2663 */
2664 if (newfile && !read_stdin && !read_buffer
2665 && mch_stat((char *)fname, &st) >= 0)
2666 {
2667 buf_store_time(curbuf, &st, fname);
2668 curbuf->b_mtime_read = curbuf->b_mtime;
2669 }
2670#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671 }
2672 msg_scroll = msg_save;
2673
2674#ifdef FEAT_VIMINFO
2675 /*
2676 * Get the marks before executing autocommands, so they can be used there.
2677 */
2678 check_marks_read();
2679#endif
2680
Bram Moolenaar071d4272004-06-13 20:20:40 +00002681 /*
Bram Moolenaar34d72d42015-07-17 14:18:08 +02002682 * We remember if the last line of the read didn't have
2683 * an eol even when 'binary' is off, to support turning 'fixeol' off,
2684 * or writing the read again with 'binary' on. The latter is required
2685 * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002686 */
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002687 curbuf->b_no_eol_lnum = read_no_eol_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002688
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02002689 /* When reloading a buffer put the cursor at the first line that is
2690 * different. */
2691 if (flags & READ_KEEP_UNDO)
2692 u_find_first_changed();
2693
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002694#ifdef FEAT_PERSISTENT_UNDO
2695 /*
2696 * When opening a new file locate undo info and read it.
2697 */
2698 if (read_undo_file)
2699 {
2700 char_u hash[UNDO_HASH_SIZE];
2701
2702 sha256_finish(&sha_ctx, hash);
Bram Moolenaar6ed8ed82010-05-30 20:40:11 +02002703 u_read_undo(NULL, hash, fname);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002704 }
2705#endif
2706
Bram Moolenaardf177f62005-02-22 08:39:57 +00002707#ifdef FEAT_AUTOCMD
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02002708 if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002709 {
2710 int m = msg_scroll;
2711 int n = msg_scrolled;
2712
2713 /* Save the fileformat now, otherwise the buffer will be considered
2714 * modified if the format/encoding was automatically detected. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002715 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002716 save_file_ff(curbuf);
2717
2718 /*
2719 * The output from the autocommands should not overwrite anything and
2720 * should not be overwritten: Set msg_scroll, restore its value if no
2721 * output was done.
2722 */
2723 msg_scroll = TRUE;
2724 if (filtering)
2725 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2726 FALSE, curbuf, eap);
Bram Moolenaarf71d7b92016-08-09 22:14:05 +02002727 else if (newfile || (read_buffer && sfname != NULL))
Bram Moolenaarc3691332016-04-20 12:49:49 +02002728 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002729 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2730 FALSE, curbuf, eap);
Bram Moolenaarc3691332016-04-20 12:49:49 +02002731 if (!au_did_filetype && *curbuf->b_p_ft != NUL)
2732 /*
2733 * EVENT_FILETYPE was not triggered but the buffer already has a
2734 * filetype. Trigger EVENT_FILETYPE using the existing filetype.
2735 */
2736 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
2737 TRUE, curbuf);
2738 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002739 else
2740 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2741 FALSE, NULL, eap);
2742 if (msg_scrolled == n)
2743 msg_scroll = m;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002744# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002745 if (aborting()) /* autocmds may abort script processing */
2746 return FAIL;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002747# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002748 }
2749#endif
2750
2751 if (recoverymode && error)
2752 return FAIL;
2753 return OK;
2754}
2755
Bram Moolenaarf04507d2016-08-20 15:05:39 +02002756#if defined(OPEN_CHR_FILES) || defined(PROTO)
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002757/*
2758 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2759 * which is the name of files used for process substitution output by
2760 * some shells on some operating systems, e.g., bash on SunOS.
2761 * Do not accept "/dev/fd/[012]", opening these may hang Vim.
2762 */
Bram Moolenaarf04507d2016-08-20 15:05:39 +02002763 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002764is_dev_fd_file(char_u *fname)
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002765{
2766 return (STRNCMP(fname, "/dev/fd/", 8) == 0
2767 && VIM_ISDIGIT(fname[8])
2768 && *skipdigits(fname + 9) == NUL
2769 && (fname[9] != NUL
2770 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
2771}
2772#endif
2773
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002774#ifdef FEAT_MBYTE
2775
2776/*
2777 * From the current line count and characters read after that, estimate the
2778 * line number where we are now.
2779 * Used for error messages that include a line number.
2780 */
2781 static linenr_T
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002782readfile_linenr(
2783 linenr_T linecnt, /* line count before reading more bytes */
2784 char_u *p, /* start of more bytes read */
2785 char_u *endp) /* end of more bytes read */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002786{
2787 char_u *s;
2788 linenr_T lnum;
2789
2790 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2791 for (s = p; s < endp; ++s)
2792 if (*s == '\n')
2793 ++lnum;
2794 return lnum;
2795}
2796#endif
2797
Bram Moolenaar071d4272004-06-13 20:20:40 +00002798/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002799 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2800 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002801 * Returns OK or FAIL.
2802 */
2803 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002804prep_exarg(exarg_T *eap, buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002805{
2806 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2807#ifdef FEAT_MBYTE
2808 + STRLEN(buf->b_p_fenc)
2809#endif
2810 + 15));
2811 if (eap->cmd == NULL)
2812 return FAIL;
2813
2814#ifdef FEAT_MBYTE
2815 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2816 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
Bram Moolenaar195d6352005-12-19 22:08:24 +00002817 eap->bad_char = buf->b_bad_char;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818#else
2819 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2820#endif
2821 eap->force_ff = 7;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002822
2823 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002824 eap->read_edit = FALSE;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002825 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002826 return OK;
2827}
2828
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002829/*
2830 * Set default or forced 'fileformat' and 'binary'.
2831 */
2832 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002833set_file_options(int set_options, exarg_T *eap)
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002834{
2835 /* set default 'fileformat' */
2836 if (set_options)
2837 {
2838 if (eap != NULL && eap->force_ff != 0)
2839 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
2840 else if (*p_ffs != NUL)
2841 set_fileformat(default_fileformat(), OPT_LOCAL);
2842 }
2843
2844 /* set or reset 'binary' */
2845 if (eap != NULL && eap->force_bin != 0)
2846 {
2847 int oldval = curbuf->b_p_bin;
2848
2849 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
2850 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
2851 }
2852}
2853
2854#if defined(FEAT_MBYTE) || defined(PROTO)
2855/*
2856 * Set forced 'fileencoding'.
2857 */
2858 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002859set_forced_fenc(exarg_T *eap)
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002860{
2861 if (eap->force_enc != 0)
2862 {
2863 char_u *fenc = enc_canonize(eap->cmd + eap->force_enc);
2864
2865 if (fenc != NULL)
2866 set_string_option_direct((char_u *)"fenc", -1,
2867 fenc, OPT_FREE|OPT_LOCAL, 0);
2868 vim_free(fenc);
2869 }
2870}
2871
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872/*
2873 * Find next fileencoding to use from 'fileencodings'.
2874 * "pp" points to fenc_next. It's advanced to the next item.
2875 * When there are no more items, an empty string is returned and *pp is set to
2876 * NULL.
2877 * When *pp is not set to NULL, the result is in allocated memory.
2878 */
2879 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002880next_fenc(char_u **pp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002881{
2882 char_u *p;
2883 char_u *r;
2884
2885 if (**pp == NUL)
2886 {
2887 *pp = NULL;
2888 return (char_u *)"";
2889 }
2890 p = vim_strchr(*pp, ',');
2891 if (p == NULL)
2892 {
2893 r = enc_canonize(*pp);
2894 *pp += STRLEN(*pp);
2895 }
2896 else
2897 {
2898 r = vim_strnsave(*pp, (int)(p - *pp));
2899 *pp = p + 1;
2900 if (r != NULL)
2901 {
2902 p = enc_canonize(r);
2903 vim_free(r);
2904 r = p;
2905 }
2906 }
2907 if (r == NULL) /* out of memory */
2908 {
2909 r = (char_u *)"";
2910 *pp = NULL;
2911 }
2912 return r;
2913}
2914
2915# ifdef FEAT_EVAL
2916/*
2917 * Convert a file with the 'charconvert' expression.
2918 * This closes the file which is to be read, converts it and opens the
2919 * resulting file for reading.
2920 * Returns name of the resulting converted file (the caller should delete it
2921 * after reading it).
2922 * Returns NULL if the conversion failed ("*fdp" is not set) .
2923 */
2924 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002925readfile_charconvert(
2926 char_u *fname, /* name of input file */
2927 char_u *fenc, /* converted from */
2928 int *fdp) /* in/out: file descriptor of file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002929{
2930 char_u *tmpname;
2931 char_u *errmsg = NULL;
2932
Bram Moolenaare5c421c2015-03-31 13:33:08 +02002933 tmpname = vim_tempname('r', FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002934 if (tmpname == NULL)
2935 errmsg = (char_u *)_("Can't find temp file for conversion");
2936 else
2937 {
2938 close(*fdp); /* close the input file, ignore errors */
2939 *fdp = -1;
2940 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2941 fname, tmpname) == FAIL)
2942 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2943 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2944 O_RDONLY | O_EXTRA, 0)) < 0)
2945 errmsg = (char_u *)_("can't read output of 'charconvert'");
2946 }
2947
2948 if (errmsg != NULL)
2949 {
2950 /* Don't use emsg(), it breaks mappings, the retry with
2951 * another type of conversion might still work. */
2952 MSG(errmsg);
2953 if (tmpname != NULL)
2954 {
2955 mch_remove(tmpname); /* delete converted file */
Bram Moolenaard23a8232018-02-10 18:45:26 +01002956 VIM_CLEAR(tmpname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002957 }
2958 }
2959
2960 /* If the input file is closed, open it (caller should check for error). */
2961 if (*fdp < 0)
2962 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2963
2964 return tmpname;
2965}
2966# endif
2967
2968#endif
2969
2970#ifdef FEAT_VIMINFO
2971/*
2972 * Read marks for the current buffer from the viminfo file, when we support
2973 * buffer marks and the buffer has a name.
2974 */
2975 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002976check_marks_read(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002977{
2978 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2979 && curbuf->b_ffname != NULL)
Bram Moolenaard812df62008-11-09 12:46:09 +00002980 read_viminfo(NULL, VIF_WANT_MARKS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002981
2982 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2983 * the ' parameter after opening a buffer. */
2984 curbuf->b_marks_read = TRUE;
2985}
2986#endif
2987
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02002988#if defined(FEAT_CRYPT) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002989/*
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002990 * Check for magic number used for encryption. Applies to the current buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2992 * *filesizep are updated.
2993 * Return the (new) encryption key, NULL for no encryption.
2994 */
2995 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01002996check_for_cryptkey(
2997 char_u *cryptkey, /* previous encryption key or NULL */
2998 char_u *ptr, /* pointer to read bytes */
2999 long *sizep, /* length of read bytes */
Bram Moolenaar8767f522016-07-01 17:17:39 +02003000 off_T *filesizep, /* nr of bytes used from file */
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003001 int newfile, /* editing a new buffer */
3002 char_u *fname, /* file name to display */
3003 int *did_ask) /* flag: whether already asked for key */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003004{
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003005 int method = crypt_method_nr_from_magic((char *)ptr, *sizep);
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02003006 int b_p_ro = curbuf->b_p_ro;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02003007
3008 if (method >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009 {
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02003010 /* Mark the buffer as read-only until the decryption has taken place.
3011 * Avoids accidentally overwriting the file with garbage. */
3012 curbuf->b_p_ro = TRUE;
3013
Bram Moolenaar2be79502014-08-13 21:58:28 +02003014 /* Set the cryptmethod local to the buffer. */
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003015 crypt_set_cm_option(curbuf, method);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02003016 if (cryptkey == NULL && !*did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003017 {
3018 if (*curbuf->b_p_key)
3019 cryptkey = curbuf->b_p_key;
3020 else
3021 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02003022 /* When newfile is TRUE, store the typed key in the 'key'
3023 * option and don't free it. bf needs hash of the key saved.
Bram Moolenaarf50a2532010-05-21 15:36:08 +02003024 * Don't ask for the key again when first time Enter was hit.
3025 * Happens when retrying to detect encoding. */
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003026 smsg((char_u *)_(need_key_msg), fname);
3027 msg_scroll = TRUE;
Bram Moolenaar3a0c9082014-11-12 15:15:42 +01003028 crypt_check_method(method);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003029 cryptkey = crypt_get_key(newfile, FALSE);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02003030 *did_ask = TRUE;
3031
Bram Moolenaar071d4272004-06-13 20:20:40 +00003032 /* check if empty key entered */
3033 if (cryptkey != NULL && *cryptkey == NUL)
3034 {
3035 if (cryptkey != curbuf->b_p_key)
3036 vim_free(cryptkey);
3037 cryptkey = NULL;
3038 }
3039 }
3040 }
3041
3042 if (cryptkey != NULL)
3043 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003044 int header_len;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02003045
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003046 curbuf->b_cryptstate = crypt_create_from_header(
3047 method, cryptkey, ptr);
3048 crypt_set_cm_option(curbuf, method);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003049
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003050 /* Remove cryptmethod specific header from the text. */
3051 header_len = crypt_get_header_len(method);
Bram Moolenaar680e0152016-09-25 20:54:11 +02003052 if (*sizep <= header_len)
3053 /* invalid header, buffer can't be encrypted */
3054 return NULL;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003055 *filesizep += header_len;
3056 *sizep -= header_len;
3057 mch_memmove(ptr, ptr + header_len, (size_t)*sizep);
3058
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02003059 /* Restore the read-only flag. */
3060 curbuf->b_p_ro = b_p_ro;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003061 }
3062 }
Bram Moolenaar40e6a712010-05-16 22:32:54 +02003063 /* When starting to edit a new file which does not have encryption, clear
3064 * the 'key' option, except when starting up (called with -x argument) */
Bram Moolenaarfa0ff9a2010-07-25 16:05:19 +02003065 else if (newfile && *curbuf->b_p_key != NUL && !starting)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003066 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
3067
3068 return cryptkey;
3069}
Bram Moolenaar80794b12010-06-13 05:20:42 +02003070#endif /* FEAT_CRYPT */
3071
Bram Moolenaar071d4272004-06-13 20:20:40 +00003072#ifdef UNIX
3073 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003074set_file_time(
3075 char_u *fname,
3076 time_t atime, /* access time */
3077 time_t mtime) /* modification time */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078{
3079# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
3080 struct utimbuf buf;
3081
3082 buf.actime = atime;
3083 buf.modtime = mtime;
3084 (void)utime((char *)fname, &buf);
3085# else
3086# if defined(HAVE_UTIMES)
3087 struct timeval tvp[2];
3088
3089 tvp[0].tv_sec = atime;
3090 tvp[0].tv_usec = 0;
3091 tvp[1].tv_sec = mtime;
3092 tvp[1].tv_usec = 0;
3093# ifdef NeXT
3094 (void)utimes((char *)fname, tvp);
3095# else
3096 (void)utimes((char *)fname, (const struct timeval *)&tvp);
3097# endif
3098# endif
3099# endif
3100}
3101#endif /* UNIX */
3102
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003103#if defined(VMS) && !defined(MIN)
3104/* Older DECC compiler for VAX doesn't define MIN() */
3105# define MIN(a, b) ((a) < (b) ? (a) : (b))
3106#endif
3107
Bram Moolenaar071d4272004-06-13 20:20:40 +00003108/*
Bram Moolenaar5386a122007-06-28 20:02:32 +00003109 * Return TRUE if a file appears to be read-only from the file permissions.
3110 */
3111 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003112check_file_readonly(
3113 char_u *fname, /* full path to file */
3114 int perm) /* known permissions on file */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003115{
3116#ifndef USE_MCH_ACCESS
3117 int fd = 0;
3118#endif
3119
3120 return (
3121#ifdef USE_MCH_ACCESS
3122# ifdef UNIX
3123 (perm & 0222) == 0 ||
3124# endif
3125 mch_access((char *)fname, W_OK)
3126#else
3127 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
3128 ? TRUE : (close(fd), FALSE)
3129#endif
3130 );
3131}
3132
3133
3134/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00003135 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00003136 *
3137 * We do our own buffering here because fwrite() is so slow.
3138 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00003139 * If "forceit" is true, we don't care for errors when attempting backups.
3140 * In case of an error everything possible is done to restore the original
Bram Moolenaare37d50a2008-08-06 17:06:04 +00003141 * file. But when "forceit" is TRUE, we risk losing it.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003142 *
3143 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
3144 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145 *
3146 * This function must NOT use NameBuff (because it's called by autowrite()).
3147 *
3148 * return FAIL for failure, OK otherwise
3149 */
3150 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003151buf_write(
3152 buf_T *buf,
3153 char_u *fname,
3154 char_u *sfname,
3155 linenr_T start,
3156 linenr_T end,
3157 exarg_T *eap, /* for forced 'ff' and 'fenc', can be
Bram Moolenaar071d4272004-06-13 20:20:40 +00003158 NULL! */
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01003159 int append, /* append to the file */
3160 int forceit,
3161 int reset_changed,
3162 int filtering)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003163{
3164 int fd;
3165 char_u *backup = NULL;
3166 int backup_copy = FALSE; /* copy the original file? */
3167 int dobackup;
3168 char_u *ffname;
3169 char_u *wfname = NULL; /* name of file to write to */
3170 char_u *s;
3171 char_u *ptr;
3172 char_u c;
3173 int len;
3174 linenr_T lnum;
3175 long nchars;
3176 char_u *errmsg = NULL;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003177 int errmsg_allocated = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 char_u *errnum = NULL;
3179 char_u *buffer;
3180 char_u smallbuf[SMBUFSIZE];
3181 char_u *backup_ext;
3182 int bufsize;
3183 long perm; /* file permissions */
3184 int retval = OK;
3185 int newfile = FALSE; /* TRUE if file doesn't exist yet */
3186 int msg_save = msg_scroll;
3187 int overwriting; /* TRUE if writing over original */
3188 int no_eol = FALSE; /* no end-of-line written */
3189 int device = FALSE; /* writing to a device */
Bram Moolenaar8767f522016-07-01 17:17:39 +02003190 stat_T st_old;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003191 int prev_got_int = got_int;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02003192 int checking_conversion;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193 int file_readonly = FALSE; /* overwritten file is read-only */
3194 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003195#if defined(UNIX) /*XXX fix me sometime? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003196 int made_writable = FALSE; /* 'w' bit has been set */
3197#endif
3198 /* writing everything */
3199 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
3200#ifdef FEAT_AUTOCMD
3201 linenr_T old_line_count = buf->b_ml.ml_line_count;
3202#endif
3203 int attr;
3204 int fileformat;
3205 int write_bin;
3206 struct bw_info write_info; /* info for buf_write_bytes() */
3207#ifdef FEAT_MBYTE
3208 int converted = FALSE;
3209 int notconverted = FALSE;
3210 char_u *fenc; /* effective 'fileencoding' */
3211 char_u *fenc_tofree = NULL; /* allocated "fenc" */
3212#endif
3213#ifdef HAS_BW_FLAGS
3214 int wb_flags = 0;
3215#endif
3216#ifdef HAVE_ACL
3217 vim_acl_T acl = NULL; /* ACL copied from original file to
3218 backup or new file */
3219#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02003220#ifdef FEAT_PERSISTENT_UNDO
3221 int write_undo_file = FALSE;
3222 context_sha256_T sha_ctx;
3223#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003224 unsigned int bkc = get_bkc_value(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225
3226 if (fname == NULL || *fname == NUL) /* safety check */
3227 return FAIL;
Bram Moolenaar70d60e92009-12-31 13:53:33 +00003228 if (buf->b_ml.ml_mfp == NULL)
3229 {
3230 /* This can happen during startup when there is a stray "w" in the
3231 * vimrc file. */
3232 EMSG(_(e_emptybuf));
3233 return FAIL;
3234 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235
3236 /*
3237 * Disallow writing from .exrc and .vimrc in current directory for
3238 * security reasons.
3239 */
3240 if (check_secure())
3241 return FAIL;
3242
3243 /* Avoid a crash for a long name. */
3244 if (STRLEN(fname) >= MAXPATHL)
3245 {
3246 EMSG(_(e_longname));
3247 return FAIL;
3248 }
3249
3250#ifdef FEAT_MBYTE
3251 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
3252 write_info.bw_conv_buf = NULL;
3253 write_info.bw_conv_error = FALSE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003254 write_info.bw_conv_error_lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003255 write_info.bw_restlen = 0;
3256# ifdef USE_ICONV
3257 write_info.bw_iconv_fd = (iconv_t)-1;
3258# endif
3259#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003260#ifdef FEAT_CRYPT
3261 write_info.bw_buffer = buf;
3262#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003263
Bram Moolenaardf177f62005-02-22 08:39:57 +00003264 /* After writing a file changedtick changes but we don't want to display
3265 * the line. */
3266 ex_no_reprint = TRUE;
3267
Bram Moolenaar071d4272004-06-13 20:20:40 +00003268 /*
3269 * If there is no file name yet, use the one for the written file.
3270 * BF_NOTEDITED is set to reflect this (in case the write fails).
3271 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003272 * Don't do this when appending.
3273 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003275 if (buf->b_ffname == NULL
3276 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00003277 && whole
3278 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00003279#ifdef FEAT_QUICKFIX
3280 && !bt_nofile(buf)
3281#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00003283 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003284 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
3285 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003286 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003287 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003288 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 }
3290
3291 if (sfname == NULL)
3292 sfname = fname;
3293 /*
3294 * For Unix: Use the short file name whenever possible.
3295 * Avoids problems with networks and when directory names are changed.
3296 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
3297 * another directory, which we don't detect
3298 */
3299 ffname = fname; /* remember full fname */
3300#ifdef UNIX
3301 fname = sfname;
3302#endif
3303
3304 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
3305 overwriting = TRUE;
3306 else
3307 overwriting = FALSE;
3308
3309 if (exiting)
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003310 settmode(TMODE_COOK); /* when exiting allow typeahead now */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003311
3312 ++no_wait_return; /* don't wait for return yet */
3313
3314 /*
3315 * Set '[ and '] marks to the lines to be written.
3316 */
3317 buf->b_op_start.lnum = start;
3318 buf->b_op_start.col = 0;
3319 buf->b_op_end.lnum = end;
3320 buf->b_op_end.col = 0;
3321
3322#ifdef FEAT_AUTOCMD
3323 {
3324 aco_save_T aco;
3325 int buf_ffname = FALSE;
3326 int buf_sfname = FALSE;
3327 int buf_fname_f = FALSE;
3328 int buf_fname_s = FALSE;
3329 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003330 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003331 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003332 bufref_T bufref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003333
3334 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003335 * Apply PRE autocommands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003336 * Set curbuf to the buffer to be written.
3337 * Careful: The autocommands may call buf_write() recursively!
3338 */
3339 if (ffname == buf->b_ffname)
3340 buf_ffname = TRUE;
3341 if (sfname == buf->b_sfname)
3342 buf_sfname = TRUE;
3343 if (fname == buf->b_ffname)
3344 buf_fname_f = TRUE;
3345 if (fname == buf->b_sfname)
3346 buf_fname_s = TRUE;
3347
3348 /* set curwin/curbuf to buf and save a few things */
3349 aucmd_prepbuf(&aco, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003350 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003351
3352 if (append)
3353 {
3354 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
3355 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003356 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003357#ifdef FEAT_QUICKFIX
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003358 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003359 nofile_err = TRUE;
3360 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003361#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003362 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003363 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003364 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003365 }
3366 else if (filtering)
3367 {
3368 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
3369 NULL, sfname, FALSE, curbuf, eap);
3370 }
3371 else if (reset_changed && whole)
3372 {
Bram Moolenaar39fc42e2011-09-02 11:56:20 +02003373 int was_changed = curbufIsChanged();
3374
3375 did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
3376 sfname, sfname, FALSE, curbuf, eap);
3377 if (did_cmd)
3378 {
3379 if (was_changed && !curbufIsChanged())
3380 {
3381 /* Written everything correctly and BufWriteCmd has reset
3382 * 'modified': Correct the undo information so that an
3383 * undo now sets 'modified'. */
3384 u_unchanged(curbuf);
3385 u_update_save_nr(curbuf);
3386 }
3387 }
3388 else
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003389 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003390#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003391 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003392 nofile_err = TRUE;
3393 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003394#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003395 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003396 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003397 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003398 }
3399 else
3400 {
3401 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
3402 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003403 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003404#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003405 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003406 nofile_err = TRUE;
3407 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003408#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003409 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003410 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003411 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003412 }
3413
3414 /* restore curwin/curbuf and a few other things */
3415 aucmd_restbuf(&aco);
3416
3417 /*
3418 * In three situations we return here and don't write the file:
3419 * 1. the autocommands deleted or unloaded the buffer.
3420 * 2. The autocommands abort script processing.
3421 * 3. If one of the "Cmd" autocommands was executed.
3422 */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003423 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003424 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003425 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar1e015462005-09-25 22:16:38 +00003426 || did_cmd || nofile_err
3427#ifdef FEAT_EVAL
3428 || aborting()
3429#endif
3430 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003431 {
3432 --no_wait_return;
3433 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003434 if (nofile_err)
3435 EMSG(_("E676: No matching autocommands for acwrite buffer"));
3436
Bram Moolenaar1e015462005-09-25 22:16:38 +00003437 if (nofile_err
3438#ifdef FEAT_EVAL
3439 || aborting()
3440#endif
3441 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003442 /* An aborting error, interrupt or exception in the
3443 * autocommands. */
3444 return FAIL;
3445 if (did_cmd)
3446 {
3447 if (buf == NULL)
3448 /* The buffer was deleted. We assume it was written
3449 * (can't retry anyway). */
3450 return OK;
3451 if (overwriting)
3452 {
3453 /* Assume the buffer was written, update the timestamp. */
3454 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00003455 if (append)
3456 buf->b_flags &= ~BF_NEW;
3457 else
3458 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003459 }
Bram Moolenaar292ad192005-12-11 21:29:51 +00003460 if (reset_changed && buf->b_changed && !append
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003461 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003462 /* Buffer still changed, the autocommands didn't work
3463 * properly. */
3464 return FAIL;
3465 return OK;
3466 }
3467#ifdef FEAT_EVAL
3468 if (!aborting())
3469#endif
3470 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
3471 return FAIL;
3472 }
3473
3474 /*
3475 * The autocommands may have changed the number of lines in the file.
3476 * When writing the whole file, adjust the end.
3477 * When writing part of the file, assume that the autocommands only
3478 * changed the number of lines that are to be written (tricky!).
3479 */
3480 if (buf->b_ml.ml_line_count != old_line_count)
3481 {
3482 if (whole) /* write all */
3483 end = buf->b_ml.ml_line_count;
3484 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
3485 end += buf->b_ml.ml_line_count - old_line_count;
3486 else /* less lines */
3487 {
3488 end -= old_line_count - buf->b_ml.ml_line_count;
3489 if (end < start)
3490 {
3491 --no_wait_return;
3492 msg_scroll = msg_save;
3493 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
3494 return FAIL;
3495 }
3496 }
3497 }
3498
3499 /*
3500 * The autocommands may have changed the name of the buffer, which may
3501 * be kept in fname, ffname and sfname.
3502 */
3503 if (buf_ffname)
3504 ffname = buf->b_ffname;
3505 if (buf_sfname)
3506 sfname = buf->b_sfname;
3507 if (buf_fname_f)
3508 fname = buf->b_ffname;
3509 if (buf_fname_s)
3510 fname = buf->b_sfname;
3511 }
3512#endif
3513
3514#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003515 if (netbeans_active() && isNetbeansBuffer(buf))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003516 {
3517 if (whole)
3518 {
3519 /*
3520 * b_changed can be 0 after an undo, but we still need to write
3521 * the buffer to NetBeans.
3522 */
3523 if (buf->b_changed || isNetbeansModified(buf))
3524 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00003525 --no_wait_return; /* may wait for return now */
3526 msg_scroll = msg_save;
3527 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003528 return retval;
3529 }
3530 else
3531 {
3532 errnum = (char_u *)"E656: ";
Bram Moolenaared0e7452008-06-27 19:17:34 +00003533 errmsg = (char_u *)_("NetBeans disallows writes of unmodified buffers");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003534 buffer = NULL;
3535 goto fail;
3536 }
3537 }
3538 else
3539 {
3540 errnum = (char_u *)"E657: ";
3541 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
3542 buffer = NULL;
3543 goto fail;
3544 }
3545 }
3546#endif
3547
3548 if (shortmess(SHM_OVER) && !exiting)
3549 msg_scroll = FALSE; /* overwrite previous file message */
3550 else
3551 msg_scroll = TRUE; /* don't overwrite previous file message */
3552 if (!filtering)
3553 filemess(buf,
3554#ifndef UNIX
3555 sfname,
3556#else
3557 fname,
3558#endif
3559 (char_u *)"", 0); /* show that we are busy */
3560 msg_scroll = FALSE; /* always overwrite the file message now */
3561
3562 buffer = alloc(BUFSIZE);
3563 if (buffer == NULL) /* can't allocate big buffer, use small
3564 * one (to be able to write when out of
3565 * memory) */
3566 {
3567 buffer = smallbuf;
3568 bufsize = SMBUFSIZE;
3569 }
3570 else
3571 bufsize = BUFSIZE;
3572
3573 /*
3574 * Get information about original file (if there is one).
3575 */
Bram Moolenaar53076832015-12-31 19:53:21 +01003576#if defined(UNIX)
Bram Moolenaar6f192452007-11-08 19:49:02 +00003577 st_old.st_dev = 0;
3578 st_old.st_ino = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003579 perm = -1;
3580 if (mch_stat((char *)fname, &st_old) < 0)
3581 newfile = TRUE;
3582 else
3583 {
3584 perm = st_old.st_mode;
3585 if (!S_ISREG(st_old.st_mode)) /* not a file */
3586 {
3587 if (S_ISDIR(st_old.st_mode))
3588 {
3589 errnum = (char_u *)"E502: ";
3590 errmsg = (char_u *)_("is a directory");
3591 goto fail;
3592 }
3593 if (mch_nodetype(fname) != NODE_WRITABLE)
3594 {
3595 errnum = (char_u *)"E503: ";
3596 errmsg = (char_u *)_("is not a file or writable device");
3597 goto fail;
3598 }
3599 /* It's a device of some kind (or a fifo) which we can write to
3600 * but for which we can't make a backup. */
3601 device = TRUE;
3602 newfile = TRUE;
3603 perm = -1;
3604 }
3605 }
3606#else /* !UNIX */
3607 /*
3608 * Check for a writable device name.
3609 */
3610 c = mch_nodetype(fname);
3611 if (c == NODE_OTHER)
3612 {
3613 errnum = (char_u *)"E503: ";
3614 errmsg = (char_u *)_("is not a file or writable device");
3615 goto fail;
3616 }
3617 if (c == NODE_WRITABLE)
3618 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003619# if defined(MSWIN)
Bram Moolenaar043545e2006-10-10 16:44:07 +00003620 /* MS-Windows allows opening a device, but we will probably get stuck
3621 * trying to write to it. */
3622 if (!p_odev)
3623 {
3624 errnum = (char_u *)"E796: ";
3625 errmsg = (char_u *)_("writing to device disabled with 'opendevice' option");
3626 goto fail;
3627 }
3628# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003629 device = TRUE;
3630 newfile = TRUE;
3631 perm = -1;
3632 }
3633 else
3634 {
3635 perm = mch_getperm(fname);
3636 if (perm < 0)
3637 newfile = TRUE;
3638 else if (mch_isdir(fname))
3639 {
3640 errnum = (char_u *)"E502: ";
3641 errmsg = (char_u *)_("is a directory");
3642 goto fail;
3643 }
3644 if (overwriting)
3645 (void)mch_stat((char *)fname, &st_old);
3646 }
3647#endif /* !UNIX */
3648
3649 if (!device && !newfile)
3650 {
3651 /*
3652 * Check if the file is really writable (when renaming the file to
3653 * make a backup we won't discover it later).
3654 */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003655 file_readonly = check_file_readonly(fname, (int)perm);
3656
Bram Moolenaar071d4272004-06-13 20:20:40 +00003657 if (!forceit && file_readonly)
3658 {
3659 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3660 {
3661 errnum = (char_u *)"E504: ";
3662 errmsg = (char_u *)_(err_readonly);
3663 }
3664 else
3665 {
3666 errnum = (char_u *)"E505: ";
3667 errmsg = (char_u *)_("is read-only (add ! to override)");
3668 }
3669 goto fail;
3670 }
3671
3672 /*
3673 * Check if the timestamp hasn't changed since reading the file.
3674 */
3675 if (overwriting)
3676 {
3677 retval = check_mtime(buf, &st_old);
3678 if (retval == FAIL)
3679 goto fail;
3680 }
3681 }
3682
3683#ifdef HAVE_ACL
3684 /*
3685 * For systems that support ACL: get the ACL from the original file.
3686 */
3687 if (!newfile)
3688 acl = mch_get_acl(fname);
3689#endif
3690
3691 /*
3692 * If 'backupskip' is not empty, don't make a backup for some files.
3693 */
3694 dobackup = (p_wb || p_bk || *p_pm != NUL);
3695#ifdef FEAT_WILDIGN
3696 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3697 dobackup = FALSE;
3698#endif
3699
3700 /*
3701 * Save the value of got_int and reset it. We don't want a previous
3702 * interruption cancel writing, only hitting CTRL-C while writing should
3703 * abort it.
3704 */
3705 prev_got_int = got_int;
3706 got_int = FALSE;
3707
3708 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3709 buf->b_saving = TRUE;
3710
3711 /*
3712 * If we are not appending or filtering, the file exists, and the
3713 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3714 * When 'patchmode' is set also make a backup when appending.
3715 *
3716 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3717 * off. This helps when editing large files on almost-full disks.
3718 */
3719 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3720 {
3721#if defined(UNIX) || defined(WIN32)
Bram Moolenaar8767f522016-07-01 17:17:39 +02003722 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003723#endif
3724
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003725 if ((bkc & BKC_YES) || append) /* "yes" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 backup_copy = TRUE;
3727#if defined(UNIX) || defined(WIN32)
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003728 else if ((bkc & BKC_AUTO)) /* "auto" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003729 {
3730 int i;
3731
3732# ifdef UNIX
3733 /*
3734 * Don't rename the file when:
3735 * - it's a hard link
3736 * - it's a symbolic link
3737 * - we don't have write permission in the directory
3738 * - we can't set the owner/group of the new file
3739 */
3740 if (st_old.st_nlink > 1
3741 || mch_lstat((char *)fname, &st) < 0
3742 || st.st_dev != st_old.st_dev
Bram Moolenaara5792f52005-11-23 21:25:05 +00003743 || st.st_ino != st_old.st_ino
3744# ifndef HAVE_FCHOWN
3745 || st.st_uid != st_old.st_uid
3746 || st.st_gid != st_old.st_gid
3747# endif
3748 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003749 backup_copy = TRUE;
3750 else
Bram Moolenaar03f48552006-02-28 23:52:23 +00003751# else
3752# ifdef WIN32
3753 /* On NTFS file systems hard links are possible. */
3754 if (mch_is_linked(fname))
3755 backup_copy = TRUE;
3756 else
3757# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003758# endif
3759 {
3760 /*
3761 * Check if we can create a file and set the owner/group to
3762 * the ones from the original file.
3763 * First find a file name that doesn't exist yet (use some
3764 * arbitrary numbers).
3765 */
3766 STRCPY(IObuff, fname);
3767 for (i = 4913; ; i += 123)
3768 {
3769 sprintf((char *)gettail(IObuff), "%d", i);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003770 if (mch_lstat((char *)IObuff, &st) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 break;
3772 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00003773 fd = mch_open((char *)IObuff,
3774 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003775 if (fd < 0) /* can't write in directory */
3776 backup_copy = TRUE;
3777 else
3778 {
3779# ifdef UNIX
Bram Moolenaara5792f52005-11-23 21:25:05 +00003780# ifdef HAVE_FCHOWN
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00003781 ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003782# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003783 if (mch_stat((char *)IObuff, &st) < 0
3784 || st.st_uid != st_old.st_uid
3785 || st.st_gid != st_old.st_gid
Bram Moolenaar78a15312009-05-15 19:33:18 +00003786 || (long)st.st_mode != perm)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003787 backup_copy = TRUE;
3788# endif
Bram Moolenaar98358622005-11-28 22:58:23 +00003789 /* Close the file before removing it, on MS-Windows we
3790 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003791 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003792 mch_remove(IObuff);
Bram Moolenaar3479c5d2010-08-08 18:46:06 +02003793# ifdef MSWIN
3794 /* MS-Windows may trigger a virus scanner to open the
3795 * file, we can't delete it then. Keep trying for half a
3796 * second. */
3797 {
3798 int try;
3799
3800 for (try = 0; try < 10; ++try)
3801 {
3802 if (mch_lstat((char *)IObuff, &st) < 0)
3803 break;
3804 ui_delay(50L, TRUE); /* wait 50 msec */
3805 mch_remove(IObuff);
3806 }
3807 }
3808# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003809 }
3810 }
3811 }
3812
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813 /*
3814 * Break symlinks and/or hardlinks if we've been asked to.
3815 */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003816 if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003817 {
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003818# ifdef UNIX
Bram Moolenaar071d4272004-06-13 20:20:40 +00003819 int lstat_res;
3820
3821 lstat_res = mch_lstat((char *)fname, &st);
3822
3823 /* Symlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003824 if ((bkc & BKC_BREAKSYMLINK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003825 && lstat_res == 0
3826 && st.st_ino != st_old.st_ino)
3827 backup_copy = FALSE;
3828
3829 /* Hardlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003830 if ((bkc & BKC_BREAKHARDLINK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003831 && st_old.st_nlink > 1
3832 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3833 backup_copy = FALSE;
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003834# else
3835# if defined(WIN32)
3836 /* Symlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003837 if ((bkc & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname))
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003838 backup_copy = FALSE;
3839
3840 /* Hardlinks. */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003841 if ((bkc & BKC_BREAKHARDLINK) && mch_is_hard_link(fname))
Bram Moolenaar12b559e2013-06-12 22:41:37 +02003842 backup_copy = FALSE;
3843# endif
3844# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003845 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003846
3847#endif
3848
3849 /* make sure we have a valid backup extension to use */
3850 if (*p_bex == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003851 backup_ext = (char_u *)".bak";
Bram Moolenaar071d4272004-06-13 20:20:40 +00003852 else
3853 backup_ext = p_bex;
3854
3855 if (backup_copy
3856 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3857 {
3858 int bfd;
3859 char_u *copybuf, *wp;
3860 int some_error = FALSE;
Bram Moolenaar8767f522016-07-01 17:17:39 +02003861 stat_T st_new;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003862 char_u *dirp;
3863 char_u *rootname;
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003864#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865 int did_set_shortname;
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003866 mode_t umask_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003867#endif
3868
3869 copybuf = alloc(BUFSIZE + 1);
3870 if (copybuf == NULL)
3871 {
3872 some_error = TRUE; /* out of memory */
3873 goto nobackup;
3874 }
3875
3876 /*
3877 * Try to make the backup in each directory in the 'bdir' option.
3878 *
3879 * Unix semantics has it, that we may have a writable file,
3880 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3881 * - the directory is not writable,
3882 * - the file may be a symbolic link,
3883 * - the file may belong to another user/group, etc.
3884 *
3885 * For these reasons, the existing writable file must be truncated
3886 * and reused. Creation of a backup COPY will be attempted.
3887 */
3888 dirp = p_bdir;
3889 while (*dirp)
3890 {
3891#ifdef UNIX
3892 st_new.st_ino = 0;
3893 st_new.st_dev = 0;
3894 st_new.st_gid = 0;
3895#endif
3896
3897 /*
3898 * Isolate one directory name, using an entry in 'bdir'.
3899 */
3900 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3901 rootname = get_file_in_dir(fname, copybuf);
3902 if (rootname == NULL)
3903 {
3904 some_error = TRUE; /* out of memory */
3905 goto nobackup;
3906 }
3907
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003908#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003909 did_set_shortname = FALSE;
3910#endif
3911
3912 /*
3913 * May try twice if 'shortname' not set.
3914 */
3915 for (;;)
3916 {
3917 /*
3918 * Make backup file name.
3919 */
Bram Moolenaar48e330a2016-02-23 14:53:34 +01003920 backup = buf_modname((buf->b_p_sn || buf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00003921 rootname, backup_ext, FALSE);
3922 if (backup == NULL)
3923 {
3924 vim_free(rootname);
3925 some_error = TRUE; /* out of memory */
3926 goto nobackup;
3927 }
3928
3929 /*
3930 * Check if backup file already exists.
3931 */
3932 if (mch_stat((char *)backup, &st_new) >= 0)
3933 {
3934#ifdef UNIX
3935 /*
3936 * Check if backup file is same as original file.
3937 * May happen when modname() gave the same file back.
3938 * E.g. silly link, or file name-length reached.
3939 * If we don't check here, we either ruin the file
3940 * when copying or erase it after writing. jw.
3941 */
3942 if (st_new.st_dev == st_old.st_dev
3943 && st_new.st_ino == st_old.st_ino)
3944 {
Bram Moolenaard23a8232018-02-10 18:45:26 +01003945 VIM_CLEAR(backup); /* no backup file to delete */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946 /*
3947 * may try again with 'shortname' set
3948 */
3949 if (!(buf->b_shortname || buf->b_p_sn))
3950 {
3951 buf->b_shortname = TRUE;
3952 did_set_shortname = TRUE;
3953 continue;
3954 }
3955 /* setting shortname didn't help */
3956 if (did_set_shortname)
3957 buf->b_shortname = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 break;
3959 }
3960#endif
3961
3962 /*
3963 * If we are not going to keep the backup file, don't
3964 * delete an existing one, try to use another name.
3965 * Change one character, just before the extension.
3966 */
3967 if (!p_bk)
3968 {
3969 wp = backup + STRLEN(backup) - 1
3970 - STRLEN(backup_ext);
3971 if (wp < backup) /* empty file name ??? */
3972 wp = backup;
3973 *wp = 'z';
3974 while (*wp > 'a'
3975 && mch_stat((char *)backup, &st_new) >= 0)
3976 --*wp;
3977 /* They all exist??? Must be something wrong. */
3978 if (*wp == 'a')
Bram Moolenaard23a8232018-02-10 18:45:26 +01003979 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003980 }
3981 }
3982 break;
3983 }
3984 vim_free(rootname);
3985
3986 /*
3987 * Try to create the backup file
3988 */
3989 if (backup != NULL)
3990 {
3991 /* remove old backup, if present */
3992 mch_remove(backup);
3993 /* Open with O_EXCL to avoid the file being created while
Bram Moolenaarcd142e32017-11-16 17:03:45 +01003994 * we were sleeping (symlink hacker attack?). Reset umask
3995 * if possible to avoid mch_setperm() below. */
3996#ifdef UNIX
3997 umask_save = umask(0);
3998#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003999 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00004000 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
4001 perm & 0777);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004002#ifdef UNIX
4003 (void)umask(umask_save);
4004#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004005 if (bfd < 0)
Bram Moolenaard23a8232018-02-10 18:45:26 +01004006 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004007 else
4008 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004009 /* Set file protection same as original file, but
4010 * strip s-bit. Only needed if umask() wasn't used
4011 * above. */
4012#ifndef UNIX
Bram Moolenaar071d4272004-06-13 20:20:40 +00004013 (void)mch_setperm(backup, perm & 0777);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004014#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015 /*
4016 * Try to set the group of the backup same as the
4017 * original file. If this fails, set the protection
4018 * bits for the group same as the protection bits for
4019 * others.
4020 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00004021 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00004022# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00004023 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00004024# endif
4025 )
4026 mch_setperm(backup,
4027 (perm & 0707) | ((perm & 07) << 3));
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004028# if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004029 mch_copy_sec(fname, backup);
4030# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004031#endif
4032
4033 /*
4034 * copy the file.
4035 */
4036 write_info.bw_fd = bfd;
4037 write_info.bw_buf = copybuf;
4038#ifdef HAS_BW_FLAGS
4039 write_info.bw_flags = FIO_NOCONVERT;
4040#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004041 while ((write_info.bw_len = read_eintr(fd, copybuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004042 BUFSIZE)) > 0)
4043 {
4044 if (buf_write_bytes(&write_info) == FAIL)
4045 {
4046 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
4047 break;
4048 }
4049 ui_breakcheck();
4050 if (got_int)
4051 {
4052 errmsg = (char_u *)_(e_interr);
4053 break;
4054 }
4055 }
4056
4057 if (close(bfd) < 0 && errmsg == NULL)
4058 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
4059 if (write_info.bw_len < 0)
4060 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
4061#ifdef UNIX
4062 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
4063#endif
4064#ifdef HAVE_ACL
4065 mch_set_acl(backup, acl);
4066#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004067#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004068 mch_copy_sec(fname, backup);
4069#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004070 break;
4071 }
4072 }
4073 }
4074 nobackup:
4075 close(fd); /* ignore errors for closing read file */
4076 vim_free(copybuf);
4077
4078 if (backup == NULL && errmsg == NULL)
4079 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
4080 /* ignore errors when forceit is TRUE */
4081 if ((some_error || errmsg != NULL) && !forceit)
4082 {
4083 retval = FAIL;
4084 goto fail;
4085 }
4086 errmsg = NULL;
4087 }
4088 else
4089 {
4090 char_u *dirp;
4091 char_u *p;
4092 char_u *rootname;
4093
4094 /*
4095 * Make a backup by renaming the original file.
4096 */
4097 /*
4098 * If 'cpoptions' includes the "W" flag, we don't want to
4099 * overwrite a read-only file. But rename may be possible
4100 * anyway, thus we need an extra check here.
4101 */
4102 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
4103 {
4104 errnum = (char_u *)"E504: ";
4105 errmsg = (char_u *)_(err_readonly);
4106 goto fail;
4107 }
4108
4109 /*
4110 *
4111 * Form the backup file name - change path/fo.o.h to
4112 * path/fo.o.h.bak Try all directories in 'backupdir', first one
4113 * that works is used.
4114 */
4115 dirp = p_bdir;
4116 while (*dirp)
4117 {
4118 /*
4119 * Isolate one directory name and make the backup file name.
4120 */
4121 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
4122 rootname = get_file_in_dir(fname, IObuff);
4123 if (rootname == NULL)
4124 backup = NULL;
4125 else
4126 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +01004127 backup = buf_modname((buf->b_p_sn || buf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00004128 rootname, backup_ext, FALSE);
4129 vim_free(rootname);
4130 }
4131
4132 if (backup != NULL)
4133 {
4134 /*
4135 * If we are not going to keep the backup file, don't
4136 * delete an existing one, try to use another name.
4137 * Change one character, just before the extension.
4138 */
4139 if (!p_bk && mch_getperm(backup) >= 0)
4140 {
4141 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
4142 if (p < backup) /* empty file name ??? */
4143 p = backup;
4144 *p = 'z';
4145 while (*p > 'a' && mch_getperm(backup) >= 0)
4146 --*p;
4147 /* They all exist??? Must be something wrong! */
4148 if (*p == 'a')
Bram Moolenaard23a8232018-02-10 18:45:26 +01004149 VIM_CLEAR(backup);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004150 }
4151 }
4152 if (backup != NULL)
4153 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004154 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00004155 * Delete any existing backup and move the current version
4156 * to the backup. For safety, we don't remove the backup
4157 * until the write has finished successfully. And if the
4158 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004159 */
4160 /*
4161 * If the renaming of the original file to the backup file
4162 * works, quit here.
4163 */
4164 if (vim_rename(fname, backup) == 0)
4165 break;
4166
Bram Moolenaard23a8232018-02-10 18:45:26 +01004167 VIM_CLEAR(backup); /* don't do the rename below */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168 }
4169 }
4170 if (backup == NULL && !forceit)
4171 {
4172 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
4173 goto fail;
4174 }
4175 }
4176 }
4177
Bram Moolenaar53076832015-12-31 19:53:21 +01004178#if defined(UNIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004179 /* When using ":w!" and the file was read-only: make it writable */
4180 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
4181 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
4182 {
4183 perm |= 0200;
4184 (void)mch_setperm(fname, perm);
4185 made_writable = TRUE;
4186 }
4187#endif
4188
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004189 /* When using ":w!" and writing to the current file, 'readonly' makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00004190 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
4191 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004192 {
4193 buf->b_p_ro = FALSE;
4194#ifdef FEAT_TITLE
4195 need_maketitle = TRUE; /* set window title later */
4196#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 status_redraw_all(); /* redraw status lines later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198 }
4199
4200 if (end > buf->b_ml.ml_line_count)
4201 end = buf->b_ml.ml_line_count;
4202 if (buf->b_ml.ml_flags & ML_EMPTY)
4203 start = end + 1;
4204
4205 /*
4206 * If the original file is being overwritten, there is a small chance that
4207 * we crash in the middle of writing. Therefore the file is preserved now.
4208 * This makes all block numbers positive so that recovery does not need
4209 * the original file.
4210 * Don't do this if there is a backup file and we are exiting.
4211 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004212 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00004213 && !(exiting && backup != NULL))
4214 {
4215 ml_preserve(buf, FALSE);
4216 if (got_int)
4217 {
4218 errmsg = (char_u *)_(e_interr);
4219 goto restore_backup;
4220 }
4221 }
4222
Bram Moolenaar071d4272004-06-13 20:20:40 +00004223#ifdef VMS
4224 vms_remove_version(fname); /* remove version */
4225#endif
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00004226 /* Default: write the file directly. May write to a temp file for
Bram Moolenaar071d4272004-06-13 20:20:40 +00004227 * multi-byte conversion. */
4228 wfname = fname;
4229
4230#ifdef FEAT_MBYTE
4231 /* Check for forced 'fileencoding' from "++opt=val" argument. */
4232 if (eap != NULL && eap->force_enc != 0)
4233 {
4234 fenc = eap->cmd + eap->force_enc;
4235 fenc = enc_canonize(fenc);
4236 fenc_tofree = fenc;
4237 }
4238 else
4239 fenc = buf->b_p_fenc;
4240
4241 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004242 * Check if the file needs to be converted.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004243 */
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004244 converted = need_conversion(fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004245
4246 /*
4247 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
4248 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
4249 * Prepare the flags for it and allocate bw_conv_buf when needed.
4250 */
4251 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
4252 {
4253 wb_flags = get_fio_flags(fenc);
4254 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
4255 {
4256 /* Need to allocate a buffer to translate into. */
4257 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
4258 write_info.bw_conv_buflen = bufsize * 2;
4259 else /* FIO_UCS4 */
4260 write_info.bw_conv_buflen = bufsize * 4;
4261 write_info.bw_conv_buf
4262 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4263 if (write_info.bw_conv_buf == NULL)
4264 end = 0;
4265 }
4266 }
4267
4268# ifdef WIN3264
4269 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
4270 {
4271 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
4272 write_info.bw_conv_buflen = bufsize * 4;
4273 write_info.bw_conv_buf
4274 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4275 if (write_info.bw_conv_buf == NULL)
4276 end = 0;
4277 }
4278# endif
4279
Bram Moolenaard0573012017-10-28 21:11:06 +02004280# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00004281 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
4282 {
4283 write_info.bw_conv_buflen = bufsize * 3;
4284 write_info.bw_conv_buf
4285 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4286 if (write_info.bw_conv_buf == NULL)
4287 end = 0;
4288 }
4289# endif
4290
4291# if defined(FEAT_EVAL) || defined(USE_ICONV)
4292 if (converted && wb_flags == 0)
4293 {
4294# ifdef USE_ICONV
4295 /*
4296 * Use iconv() conversion when conversion is needed and it's not done
4297 * internally.
4298 */
4299 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
4300 enc_utf8 ? (char_u *)"utf-8" : p_enc);
4301 if (write_info.bw_iconv_fd != (iconv_t)-1)
4302 {
4303 /* We're going to use iconv(), allocate a buffer to convert in. */
4304 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
4305 write_info.bw_conv_buf
4306 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4307 if (write_info.bw_conv_buf == NULL)
4308 end = 0;
4309 write_info.bw_first = TRUE;
4310 }
4311# ifdef FEAT_EVAL
4312 else
4313# endif
4314# endif
4315
4316# ifdef FEAT_EVAL
4317 /*
4318 * When the file needs to be converted with 'charconvert' after
4319 * writing, write to a temp file instead and let the conversion
4320 * overwrite the original file.
4321 */
4322 if (*p_ccv != NUL)
4323 {
Bram Moolenaare5c421c2015-03-31 13:33:08 +02004324 wfname = vim_tempname('w', FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004325 if (wfname == NULL) /* Can't write without a tempfile! */
4326 {
4327 errmsg = (char_u *)_("E214: Can't find temp file for writing");
4328 goto restore_backup;
4329 }
4330 }
4331# endif
4332 }
4333# endif
4334 if (converted && wb_flags == 0
4335# ifdef USE_ICONV
4336 && write_info.bw_iconv_fd == (iconv_t)-1
4337# endif
4338# ifdef FEAT_EVAL
4339 && wfname == fname
4340# endif
4341 )
4342 {
4343 if (!forceit)
4344 {
4345 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
4346 goto restore_backup;
4347 }
4348 notconverted = TRUE;
4349 }
4350#endif
4351
4352 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004353 * If conversion is taking place, we may first pretend to write and check
4354 * for conversion errors. Then loop again to write for real.
4355 * When not doing conversion this writes for real right away.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004356 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004357 for (checking_conversion = TRUE; ; checking_conversion = FALSE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004358 {
4359 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004360 * There is no need to check conversion when:
4361 * - there is no conversion
4362 * - we make a backup file, that can be restored in case of conversion
4363 * failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004364 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004365#ifdef FEAT_MBYTE
4366 if (!converted || dobackup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004367#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004368 checking_conversion = FALSE;
4369
4370 if (checking_conversion)
4371 {
4372 /* Make sure we don't write anything. */
4373 fd = -1;
4374 write_info.bw_fd = fd;
4375 }
4376 else
4377 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004378#ifdef HAVE_FTRUNCATE
4379# define TRUNC_ON_OPEN 0
4380#else
4381# define TRUNC_ON_OPEN O_TRUNC
4382#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004383 /*
4384 * Open the file "wfname" for writing.
4385 * We may try to open the file twice: If we can't write to the file
4386 * and forceit is TRUE we delete the existing file and try to
4387 * create a new one. If this still fails we may have lost the
4388 * original file! (this may happen when the user reached his
4389 * quotum for number of files).
4390 * Appending will fail if the file does not exist and forceit is
4391 * FALSE.
4392 */
4393 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
4394 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004395 : (O_CREAT | TRUNC_ON_OPEN))
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004396 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004398 /*
4399 * A forced write will try to create a new file if the old one
4400 * is still readonly. This may also happen when the directory
4401 * is read-only. In that case the mch_remove() will fail.
4402 */
4403 if (errmsg == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004404 {
4405#ifdef UNIX
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004406 stat_T st;
4407
4408 /* Don't delete the file when it's a hard or symbolic link.
4409 */
4410 if ((!newfile && st_old.st_nlink > 1)
4411 || (mch_lstat((char *)fname, &st) == 0
4412 && (st.st_dev != st_old.st_dev
4413 || st.st_ino != st_old.st_ino)))
4414 errmsg = (char_u *)_("E166: Can't open linked file for writing");
4415 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004416#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004417 {
4418 errmsg = (char_u *)_("E212: Can't open file for writing");
4419 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
4420 && perm >= 0)
4421 {
4422#ifdef UNIX
4423 /* we write to the file, thus it should be marked
4424 writable after all */
4425 if (!(perm & 0200))
4426 made_writable = TRUE;
4427 perm |= 0200;
4428 if (st_old.st_uid != getuid()
4429 || st_old.st_gid != getgid())
4430 perm &= 0777;
4431#endif
4432 if (!append) /* don't remove when appending */
4433 mch_remove(wfname);
4434 continue;
4435 }
4436 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004437 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438
4439restore_backup:
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004441 stat_T st;
4442
Bram Moolenaar071d4272004-06-13 20:20:40 +00004443 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004444 * If we failed to open the file, we don't need a backup.
4445 * Throw it away. If we moved or removed the original file
4446 * try to put the backup in its place.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004447 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004448 if (backup != NULL && wfname == fname)
4449 {
4450 if (backup_copy)
4451 {
4452 /*
4453 * There is a small chance that we removed the
4454 * original, try to move the copy in its place.
4455 * This may not work if the vim_rename() fails.
4456 * In that case we leave the copy around.
4457 */
4458 /* If file does not exist, put the copy in its
4459 * place */
4460 if (mch_stat((char *)fname, &st) < 0)
4461 vim_rename(backup, fname);
4462 /* if original file does exist throw away the copy
4463 */
4464 if (mch_stat((char *)fname, &st) >= 0)
4465 mch_remove(backup);
4466 }
4467 else
4468 {
4469 /* try to put the original file back */
4470 vim_rename(backup, fname);
4471 }
4472 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004474 /* if original file no longer exists give an extra warning
4475 */
4476 if (!newfile && mch_stat((char *)fname, &st) < 0)
4477 end = 0;
4478 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004479
4480#ifdef FEAT_MBYTE
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004481 if (wfname != fname)
4482 vim_free(wfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004483#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004484 goto fail;
4485 }
4486 write_info.bw_fd = fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004487
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004488#if defined(UNIX)
4489 {
4490 stat_T st;
4491
4492 /* Double check we are writing the intended file before making
4493 * any changes. */
4494 if (overwriting
4495 && (!dobackup || backup_copy)
4496 && fname == wfname
4497 && perm >= 0
4498 && mch_fstat(fd, &st) == 0
4499 && st.st_ino != st_old.st_ino)
4500 {
4501 close(fd);
4502 errmsg = (char_u *)_("E949: File changed while writing");
4503 goto fail;
4504 }
4505 }
4506#endif
4507#ifdef HAVE_FTRUNCATE
4508 if (!append)
Bram Moolenaarae1e1082017-11-17 21:35:24 +01004509 ignored = ftruncate(fd, (off_t)0);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004510#endif
4511
Bram Moolenaard0573012017-10-28 21:11:06 +02004512#if defined(WIN3264)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004513 if (backup != NULL && overwriting && !append)
4514 {
4515 if (backup_copy)
4516 (void)mch_copy_file_attribute(wfname, backup);
4517 else
4518 (void)mch_copy_file_attribute(backup, wfname);
4519 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004520
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004521 if (!overwriting && !append)
4522 {
4523 if (buf->b_ffname != NULL)
4524 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
4525 /* Should copy resource fork */
4526 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004527#endif
4528
Bram Moolenaar071d4272004-06-13 20:20:40 +00004529#ifdef FEAT_CRYPT
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004530 if (*buf->b_p_key != NUL && !filtering)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004531 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004532 char_u *header;
4533 int header_len;
4534
4535 buf->b_cryptstate = crypt_create_for_writing(
4536 crypt_get_method_nr(buf),
4537 buf->b_p_key, &header, &header_len);
4538 if (buf->b_cryptstate == NULL || header == NULL)
4539 end = 0;
4540 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004541 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004542 /* Write magic number, so that Vim knows how this file is
4543 * encrypted when reading it back. */
4544 write_info.bw_buf = header;
4545 write_info.bw_len = header_len;
4546 write_info.bw_flags = FIO_NOCONVERT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004547 if (buf_write_bytes(&write_info) == FAIL)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004548 end = 0;
4549 wb_flags |= FIO_ENCRYPTED;
4550 vim_free(header);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004552 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004553#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004554 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004555 errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004556
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004557 write_info.bw_buf = buffer;
4558 nchars = 0;
4559
4560 /* use "++bin", "++nobin" or 'binary' */
4561 if (eap != NULL && eap->force_bin != 0)
4562 write_bin = (eap->force_bin == FORCE_BIN);
4563 else
4564 write_bin = buf->b_p_bin;
4565
4566#ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00004567 /*
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004568 * The BOM is written just after the encryption magic number.
4569 * Skip it when appending and the file already existed, the BOM only
4570 * makes sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571 */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004572 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004573 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004574 write_info.bw_len = make_bom(buffer, fenc);
4575 if (write_info.bw_len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004576 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004577 /* don't convert, do encryption */
4578 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4579 if (buf_write_bytes(&write_info) == FAIL)
4580 end = 0;
4581 else
4582 nchars += write_info.bw_len;
4583 }
4584 }
4585 write_info.bw_start_lnum = start;
4586#endif
4587
4588#ifdef FEAT_PERSISTENT_UNDO
4589 write_undo_file = (buf->b_p_udf
4590 && overwriting
4591 && !append
4592 && !filtering
4593 && reset_changed
4594 && !checking_conversion);
4595 if (write_undo_file)
4596 /* Prepare for computing the hash value of the text. */
4597 sha256_start(&sha_ctx);
4598#endif
4599
4600 write_info.bw_len = bufsize;
4601#ifdef HAS_BW_FLAGS
4602 write_info.bw_flags = wb_flags;
4603#endif
4604 fileformat = get_fileformat_force(buf, eap);
4605 s = buffer;
4606 len = 0;
4607 for (lnum = start; lnum <= end; ++lnum)
4608 {
4609 /*
4610 * The next while loop is done once for each character written.
4611 * Keep it fast!
4612 */
4613 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
4614#ifdef FEAT_PERSISTENT_UNDO
4615 if (write_undo_file)
4616 sha256_update(&sha_ctx, ptr + 1,
4617 (UINT32_T)(STRLEN(ptr + 1) + 1));
4618#endif
4619 while ((c = *++ptr) != NUL)
4620 {
4621 if (c == NL)
4622 *s = NUL; /* replace newlines with NULs */
4623 else if (c == CAR && fileformat == EOL_MAC)
4624 *s = NL; /* Mac: replace CRs with NLs */
4625 else
4626 *s = c;
4627 ++s;
4628 if (++len != bufsize)
4629 continue;
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004630 if (buf_write_bytes(&write_info) == FAIL)
4631 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004632 end = 0; /* write error: break loop */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004633 break;
4634 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004635 nchars += bufsize;
4636 s = buffer;
4637 len = 0;
4638#ifdef FEAT_MBYTE
4639 write_info.bw_start_lnum = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004640#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004641 }
4642 /* write failed or last line has no EOL: stop here */
4643 if (end == 0
4644 || (lnum == end
4645 && (write_bin || !buf->b_p_fixeol)
4646 && (lnum == buf->b_no_eol_lnum
4647 || (lnum == buf->b_ml.ml_line_count
4648 && !buf->b_p_eol))))
4649 {
4650 ++lnum; /* written the line, count it */
4651 no_eol = TRUE;
4652 break;
4653 }
4654 if (fileformat == EOL_UNIX)
4655 *s++ = NL;
4656 else
4657 {
4658 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4659 if (fileformat == EOL_DOS) /* write CR-NL */
4660 {
4661 if (++len == bufsize)
4662 {
4663 if (buf_write_bytes(&write_info) == FAIL)
4664 {
4665 end = 0; /* write error: break loop */
4666 break;
4667 }
4668 nchars += bufsize;
4669 s = buffer;
4670 len = 0;
4671 }
4672 *s++ = NL;
4673 }
4674 }
4675 if (++len == bufsize && end)
4676 {
4677 if (buf_write_bytes(&write_info) == FAIL)
4678 {
4679 end = 0; /* write error: break loop */
4680 break;
4681 }
4682 nchars += bufsize;
4683 s = buffer;
4684 len = 0;
4685
4686 ui_breakcheck();
4687 if (got_int)
4688 {
4689 end = 0; /* Interrupted, break loop */
4690 break;
4691 }
4692 }
4693#ifdef VMS
4694 /*
4695 * On VMS there is a problem: newlines get added when writing
4696 * blocks at a time. Fix it by writing a line at a time.
4697 * This is much slower!
4698 * Explanation: VAX/DECC RTL insists that records in some RMS
4699 * structures end with a newline (carriage return) character, and
4700 * if they don't it adds one.
4701 * With other RMS structures it works perfect without this fix.
4702 */
4703 if (buf->b_fab_rfm == FAB$C_VFC
4704 || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4705 {
4706 int b2write;
4707
4708 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4709 ? MIN(4096, bufsize)
4710 : MIN(buf->b_fab_mrs, bufsize));
4711
4712 b2write = len;
4713 while (b2write > 0)
4714 {
4715 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4716 if (buf_write_bytes(&write_info) == FAIL)
4717 {
4718 end = 0;
4719 break;
4720 }
4721 b2write -= MIN(b2write, buf->b_fab_mrs);
4722 }
4723 write_info.bw_len = bufsize;
4724 nchars += len;
4725 s = buffer;
4726 len = 0;
4727 }
4728#endif
4729 }
4730 if (len > 0 && end > 0)
4731 {
4732 write_info.bw_len = len;
4733 if (buf_write_bytes(&write_info) == FAIL)
4734 end = 0; /* write error */
4735 nchars += len;
4736 }
4737
4738 /* Stop when writing done or an error was encountered. */
4739 if (!checking_conversion || end == 0)
4740 break;
4741
4742 /* If no error happened until now, writing should be ok, so loop to
4743 * really write the buffer. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004744 }
4745
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004746 /* If we started writing, finish writing. Also when an error was
4747 * encountered. */
4748 if (!checking_conversion)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004750#if defined(UNIX) && defined(HAVE_FSYNC)
4751 /*
4752 * On many journalling file systems there is a bug that causes both the
4753 * original and the backup file to be lost when halting the system
4754 * right after writing the file. That's because only the meta-data is
4755 * journalled. Syncing the file slows down the system, but assures it
4756 * has been written to disk and we don't lose it.
4757 * For a device do try the fsync() but don't complain if it does not
4758 * work (could be a pipe).
4759 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
4760 */
4761 if (p_fs && fsync(fd) != 0 && !device)
4762 {
Bram Moolenaar7567d0b2017-11-16 23:04:15 +01004763 errmsg = (char_u *)_(e_fsync);
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004764 end = 0;
4765 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004766#endif
4767
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004768#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004769 /* Probably need to set the security context. */
4770 if (!backup_copy)
4771 mch_copy_sec(backup, wfname);
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004772#endif
4773
Bram Moolenaara5792f52005-11-23 21:25:05 +00004774#ifdef UNIX
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004775 /* When creating a new file, set its owner/group to that of the
4776 * original file. Get the new device and inode number. */
4777 if (backup != NULL && !backup_copy)
Bram Moolenaara5792f52005-11-23 21:25:05 +00004778 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004779# ifdef HAVE_FCHOWN
4780 stat_T st;
4781
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004782 /* Don't change the owner when it's already OK, some systems remove
4783 * permission or ACL stuff. */
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004784 if (mch_stat((char *)wfname, &st) < 0
4785 || st.st_uid != st_old.st_uid
4786 || st.st_gid != st_old.st_gid)
4787 {
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004788 /* changing owner might not be possible */
4789 ignored = fchown(fd, st_old.st_uid, -1);
4790 /* if changing group fails clear the group permissions */
4791 if (fchown(fd, -1, st_old.st_gid) == -1 && perm > 0)
4792 perm &= ~070;
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004793 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00004794# endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004795 buf_setino(buf);
4796 }
4797 else if (!buf->b_dev_valid)
4798 /* Set the inode when creating a new file. */
4799 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004800#endif
4801
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004802#ifdef UNIX
4803 if (made_writable)
4804 perm &= ~0200; /* reset 'w' bit for security reasons */
4805#endif
4806#ifdef HAVE_FCHMOD
4807 /* set permission of new file same as old file */
4808 if (perm >= 0)
4809 (void)mch_fsetperm(fd, perm);
4810#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004811 if (close(fd) != 0)
4812 {
4813 errmsg = (char_u *)_("E512: Close failed");
4814 end = 0;
4815 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004817#ifndef HAVE_FCHMOD
4818 /* set permission of new file same as old file */
4819 if (perm >= 0)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004820 (void)mch_setperm(wfname, perm);
Bram Moolenaarcd142e32017-11-16 17:03:45 +01004821#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004822#ifdef HAVE_ACL
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004823 /*
4824 * Probably need to set the ACL before changing the user (can't set the
4825 * ACL on a file the user doesn't own).
4826 * On Solaris, with ZFS and the aclmode property set to "discard" (the
4827 * default), chmod() discards all part of a file's ACL that don't
4828 * represent the mode of the file. It's non-trivial for us to discover
4829 * whether we're in that situation, so we simply always re-set the ACL.
4830 */
Bram Moolenaarda412772016-07-14 20:37:07 +02004831# ifndef HAVE_SOLARIS_ZFS_ACL
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004832 if (!backup_copy)
Bram Moolenaarda412772016-07-14 20:37:07 +02004833# endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004834 mch_set_acl(wfname, acl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004835#endif
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004836#ifdef FEAT_CRYPT
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004837 if (buf->b_cryptstate != NULL)
4838 {
4839 crypt_free_state(buf->b_cryptstate);
4840 buf->b_cryptstate = NULL;
4841 }
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004842#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004843
Bram Moolenaar071d4272004-06-13 20:20:40 +00004844#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004845 if (wfname != fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004846 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004847 /*
4848 * The file was written to a temp file, now it needs to be
4849 * converted with 'charconvert' to (overwrite) the output file.
4850 */
4851 if (end != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004853 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc,
4854 fenc, wfname, fname) == FAIL)
4855 {
4856 write_info.bw_conv_error = TRUE;
4857 end = 0;
4858 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004859 }
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004860 mch_remove(wfname);
4861 vim_free(wfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004862 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004863#endif
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004864 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004865
4866 if (end == 0)
4867 {
Bram Moolenaare6bf6552017-06-27 22:11:51 +02004868 /*
4869 * Error encountered.
4870 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871 if (errmsg == NULL)
4872 {
4873#ifdef FEAT_MBYTE
4874 if (write_info.bw_conv_error)
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004875 {
4876 if (write_info.bw_conv_error_lnum == 0)
4877 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
4878 else
4879 {
4880 errmsg_allocated = TRUE;
4881 errmsg = alloc(300);
4882 vim_snprintf((char *)errmsg, 300, _("E513: write error, conversion failed in line %ld (make 'fenc' empty to override)"),
4883 (long)write_info.bw_conv_error_lnum);
4884 }
4885 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 else
4887#endif
4888 if (got_int)
4889 errmsg = (char_u *)_(e_interr);
4890 else
4891 errmsg = (char_u *)_("E514: write error (file system full?)");
4892 }
4893
4894 /*
4895 * If we have a backup file, try to put it in place of the new file,
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004896 * because the new file is probably corrupt. This avoids losing the
Bram Moolenaar071d4272004-06-13 20:20:40 +00004897 * original file when trying to make a backup when writing the file a
4898 * second time.
4899 * When "backup_copy" is set we need to copy the backup over the new
4900 * file. Otherwise rename the backup file.
4901 * If this is OK, don't give the extra warning message.
4902 */
4903 if (backup != NULL)
4904 {
4905 if (backup_copy)
4906 {
4907 /* This may take a while, if we were interrupted let the user
4908 * know we got the message. */
4909 if (got_int)
4910 {
4911 MSG(_(e_interr));
4912 out_flush();
4913 }
4914 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4915 {
4916 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004917 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4918 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004919 {
4920 /* copy the file. */
4921 write_info.bw_buf = smallbuf;
4922#ifdef HAS_BW_FLAGS
4923 write_info.bw_flags = FIO_NOCONVERT;
4924#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004925 while ((write_info.bw_len = read_eintr(fd, smallbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004926 SMBUFSIZE)) > 0)
4927 if (buf_write_bytes(&write_info) == FAIL)
4928 break;
4929
4930 if (close(write_info.bw_fd) >= 0
4931 && write_info.bw_len == 0)
4932 end = 1; /* success */
4933 }
4934 close(fd); /* ignore errors for closing read file */
4935 }
4936 }
4937 else
4938 {
4939 if (vim_rename(backup, fname) == 0)
4940 end = 1;
4941 }
4942 }
4943 goto fail;
4944 }
4945
4946 lnum -= start; /* compute number of written lines */
4947 --no_wait_return; /* may wait for return now */
4948
4949#if !(defined(UNIX) || defined(VMS))
4950 fname = sfname; /* use shortname now, for the messages */
4951#endif
4952 if (!filtering)
4953 {
4954 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4955 c = FALSE;
4956#ifdef FEAT_MBYTE
4957 if (write_info.bw_conv_error)
4958 {
4959 STRCAT(IObuff, _(" CONVERSION ERROR"));
4960 c = TRUE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004961 if (write_info.bw_conv_error_lnum != 0)
Bram Moolenaara800b422010-06-27 01:15:55 +02004962 vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %ld;"),
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004963 (long)write_info.bw_conv_error_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004964 }
4965 else if (notconverted)
4966 {
4967 STRCAT(IObuff, _("[NOT converted]"));
4968 c = TRUE;
4969 }
4970 else if (converted)
4971 {
4972 STRCAT(IObuff, _("[converted]"));
4973 c = TRUE;
4974 }
4975#endif
4976 if (device)
4977 {
4978 STRCAT(IObuff, _("[Device]"));
4979 c = TRUE;
4980 }
4981 else if (newfile)
4982 {
4983 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4984 c = TRUE;
4985 }
4986 if (no_eol)
4987 {
4988 msg_add_eol();
4989 c = TRUE;
4990 }
4991 /* may add [unix/dos/mac] */
4992 if (msg_add_fileformat(fileformat))
4993 c = TRUE;
4994#ifdef FEAT_CRYPT
4995 if (wb_flags & FIO_ENCRYPTED)
4996 {
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02004997 crypt_append_msg(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004998 c = TRUE;
4999 }
5000#endif
5001 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
5002 if (!shortmess(SHM_WRITE))
5003 {
5004 if (append)
5005 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
5006 else
5007 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
5008 }
5009
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00005010 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005011 }
5012
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005013 /* When written everything correctly: reset 'modified'. Unless not
5014 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00005015 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00005016#ifdef FEAT_MBYTE
5017 && !write_info.bw_conv_error
5018#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005019 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
5020 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005021 {
5022 unchanged(buf, TRUE);
Bram Moolenaar086329d2014-10-31 19:51:36 +01005023#ifdef FEAT_AUTOCMD
Bram Moolenaar95c526e2017-02-25 14:59:34 +01005024 /* b:changedtick is always incremented in unchanged() but that
Bram Moolenaar086329d2014-10-31 19:51:36 +01005025 * should not trigger a TextChanged event. */
Bram Moolenaar5a093432018-02-10 18:15:19 +01005026 if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf))
5027 buf->b_last_changedtick = CHANGEDTICK(buf);
Bram Moolenaar086329d2014-10-31 19:51:36 +01005028#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029 u_unchanged(buf);
Bram Moolenaar730cde92010-06-27 05:18:54 +02005030 u_update_save_nr(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031 }
5032
5033 /*
5034 * If written to the current file, update the timestamp of the swap file
5035 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
5036 */
5037 if (overwriting)
5038 {
5039 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00005040 if (append)
5041 buf->b_flags &= ~BF_NEW;
5042 else
5043 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044 }
5045
5046 /*
5047 * If we kept a backup until now, and we are in patch mode, then we make
5048 * the backup file our 'original' file.
5049 */
5050 if (*p_pm && dobackup)
5051 {
Bram Moolenaar48e330a2016-02-23 14:53:34 +01005052 char *org = (char *)buf_modname((buf->b_p_sn || buf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005053 fname, p_pm, FALSE);
5054
5055 if (backup != NULL)
5056 {
Bram Moolenaar8767f522016-07-01 17:17:39 +02005057 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005058
5059 /*
5060 * If the original file does not exist yet
5061 * the current backup file becomes the original file
5062 */
5063 if (org == NULL)
5064 EMSG(_("E205: Patchmode: can't save original file"));
5065 else if (mch_stat(org, &st) < 0)
5066 {
5067 vim_rename(backup, (char_u *)org);
Bram Moolenaard23a8232018-02-10 18:45:26 +01005068 VIM_CLEAR(backup); /* don't delete the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005069#ifdef UNIX
5070 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
5071#endif
5072 }
5073 }
5074 /*
5075 * If there is no backup file, remember that a (new) file was
5076 * created.
5077 */
5078 else
5079 {
5080 int empty_fd;
5081
5082 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00005083 || (empty_fd = mch_open(org,
5084 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00005085 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005086 EMSG(_("E206: patchmode: can't touch empty original file"));
5087 else
5088 close(empty_fd);
5089 }
5090 if (org != NULL)
5091 {
5092 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
5093 vim_free(org);
5094 }
5095 }
5096
5097 /*
5098 * Remove the backup unless 'backup' option is set
5099 */
5100 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
5101 EMSG(_("E207: Can't delete backup file"));
5102
5103#ifdef FEAT_SUN_WORKSHOP
5104 if (usingSunWorkShop)
5105 workshop_file_saved((char *) ffname);
5106#endif
5107
5108 goto nofail;
5109
5110 /*
5111 * Finish up. We get here either after failure or success.
5112 */
5113fail:
5114 --no_wait_return; /* may wait for return now */
5115nofail:
5116
5117 /* Done saving, we accept changed buffer warnings again */
5118 buf->b_saving = FALSE;
5119
5120 vim_free(backup);
5121 if (buffer != smallbuf)
5122 vim_free(buffer);
5123#ifdef FEAT_MBYTE
5124 vim_free(fenc_tofree);
5125 vim_free(write_info.bw_conv_buf);
5126# ifdef USE_ICONV
5127 if (write_info.bw_iconv_fd != (iconv_t)-1)
5128 {
5129 iconv_close(write_info.bw_iconv_fd);
5130 write_info.bw_iconv_fd = (iconv_t)-1;
5131 }
5132# endif
5133#endif
5134#ifdef HAVE_ACL
5135 mch_free_acl(acl);
5136#endif
5137
5138 if (errmsg != NULL)
5139 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005140 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141
Bram Moolenaar8820b482017-03-16 17:23:31 +01005142 attr = HL_ATTR(HLF_E); /* set highlight for error messages */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005143 msg_add_fname(buf,
5144#ifndef UNIX
5145 sfname
5146#else
5147 fname
5148#endif
5149 ); /* put file name in IObuff with quotes */
5150 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
5151 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
5152 /* If the error message has the form "is ...", put the error number in
5153 * front of the file name. */
5154 if (errnum != NULL)
5155 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00005156 STRMOVE(IObuff + numlen, IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005157 mch_memmove(IObuff, errnum, (size_t)numlen);
5158 }
5159 STRCAT(IObuff, errmsg);
5160 emsg(IObuff);
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005161 if (errmsg_allocated)
5162 vim_free(errmsg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163
5164 retval = FAIL;
5165 if (end == 0)
5166 {
5167 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
5168 attr | MSG_HIST);
5169 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
5170 attr | MSG_HIST);
5171
5172 /* Update the timestamp to avoid an "overwrite changed file"
5173 * prompt when writing again. */
5174 if (mch_stat((char *)fname, &st_old) >= 0)
5175 {
5176 buf_store_time(buf, &st_old, fname);
5177 buf->b_mtime_read = buf->b_mtime;
5178 }
5179 }
5180 }
5181 msg_scroll = msg_save;
5182
Bram Moolenaar55debbe2010-05-23 23:34:36 +02005183#ifdef FEAT_PERSISTENT_UNDO
5184 /*
5185 * When writing the whole file and 'undofile' is set, also write the undo
5186 * file.
5187 */
5188 if (retval == OK && write_undo_file)
5189 {
5190 char_u hash[UNDO_HASH_SIZE];
5191
5192 sha256_finish(&sha_ctx, hash);
5193 u_write_undo(NULL, FALSE, buf, hash);
5194 }
5195#endif
5196
Bram Moolenaar071d4272004-06-13 20:20:40 +00005197#ifdef FEAT_AUTOCMD
5198#ifdef FEAT_EVAL
5199 if (!should_abort(retval))
5200#else
5201 if (!got_int)
5202#endif
5203 {
5204 aco_save_T aco;
5205
Bram Moolenaar68a33fc2012-04-25 16:50:48 +02005206 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
5207
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 /*
5209 * Apply POST autocommands.
5210 * Careful: The autocommands may call buf_write() recursively!
5211 */
5212 aucmd_prepbuf(&aco, buf);
5213
5214 if (append)
5215 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
5216 FALSE, curbuf, eap);
5217 else if (filtering)
5218 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
5219 FALSE, curbuf, eap);
5220 else if (reset_changed && whole)
5221 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
5222 FALSE, curbuf, eap);
5223 else
5224 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
5225 FALSE, curbuf, eap);
5226
5227 /* restore curwin/curbuf and a few other things */
5228 aucmd_restbuf(&aco);
5229
5230#ifdef FEAT_EVAL
5231 if (aborting()) /* autocmds may abort script processing */
5232 retval = FALSE;
5233#endif
5234 }
5235#endif
5236
5237 got_int |= prev_got_int;
5238
Bram Moolenaar071d4272004-06-13 20:20:40 +00005239 return retval;
5240}
5241
5242/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005243 * Set the name of the current buffer. Use when the buffer doesn't have a
5244 * name and a ":r" or ":w" command with a file name is used.
5245 */
5246 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005247set_rw_fname(char_u *fname, char_u *sfname)
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005248{
5249#ifdef FEAT_AUTOCMD
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005250 buf_T *buf = curbuf;
5251
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005252 /* It's like the unnamed buffer is deleted.... */
5253 if (curbuf->b_p_bl)
5254 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
5255 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
5256# ifdef FEAT_EVAL
5257 if (aborting()) /* autocmds may abort script processing */
5258 return FAIL;
5259# endif
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005260 if (curbuf != buf)
5261 {
5262 /* We are in another buffer now, don't do the renaming. */
5263 EMSG(_(e_auchangedbuf));
5264 return FAIL;
5265 }
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005266#endif
5267
5268 if (setfname(curbuf, fname, sfname, FALSE) == OK)
5269 curbuf->b_flags |= BF_NOTEDITED;
5270
5271#ifdef FEAT_AUTOCMD
5272 /* ....and a new named one is created */
5273 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
5274 if (curbuf->b_p_bl)
5275 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
5276# ifdef FEAT_EVAL
5277 if (aborting()) /* autocmds may abort script processing */
5278 return FAIL;
5279# endif
5280
5281 /* Do filetype detection now if 'filetype' is empty. */
5282 if (*curbuf->b_p_ft == NUL)
5283 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005284 if (au_has_group((char_u *)"filetypedetect"))
Bram Moolenaar1610d052016-06-09 22:53:01 +02005285 (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE, NULL);
Bram Moolenaara3227e22006-03-08 21:32:40 +00005286 do_modelines(0);
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005287 }
5288#endif
5289
5290 return OK;
5291}
5292
5293/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005294 * Put file name into IObuff with quotes.
5295 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005296 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005297msg_add_fname(buf_T *buf, char_u *fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005298{
5299 if (fname == NULL)
5300 fname = (char_u *)"-stdin-";
5301 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
5302 IObuff[0] = '"';
5303 STRCAT(IObuff, "\" ");
5304}
5305
5306/*
5307 * Append message for text mode to IObuff.
5308 * Return TRUE if something appended.
5309 */
5310 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005311msg_add_fileformat(int eol_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005312{
5313#ifndef USE_CRNL
5314 if (eol_type == EOL_DOS)
5315 {
5316 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
5317 return TRUE;
5318 }
5319#endif
5320#ifndef USE_CR
5321 if (eol_type == EOL_MAC)
5322 {
5323 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
5324 return TRUE;
5325 }
5326#endif
5327#if defined(USE_CRNL) || defined(USE_CR)
5328 if (eol_type == EOL_UNIX)
5329 {
5330 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
5331 return TRUE;
5332 }
5333#endif
5334 return FALSE;
5335}
5336
5337/*
5338 * Append line and character count to IObuff.
5339 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005340 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005341msg_add_lines(
5342 int insert_space,
5343 long lnum,
Bram Moolenaar8767f522016-07-01 17:17:39 +02005344 off_T nchars)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005345{
5346 char_u *p;
5347
5348 p = IObuff + STRLEN(IObuff);
5349
5350 if (insert_space)
5351 *p++ = ' ';
5352 if (shortmess(SHM_LINES))
Bram Moolenaarbde98102016-07-01 20:03:42 +02005353 vim_snprintf((char *)p, IOSIZE - (p - IObuff),
5354 "%ldL, %lldC", lnum, (varnumber_T)nchars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005355 else
5356 {
5357 if (lnum == 1)
5358 STRCPY(p, _("1 line, "));
5359 else
5360 sprintf((char *)p, _("%ld lines, "), lnum);
5361 p += STRLEN(p);
5362 if (nchars == 1)
5363 STRCPY(p, _("1 character"));
5364 else
Bram Moolenaarbde98102016-07-01 20:03:42 +02005365 vim_snprintf((char *)p, IOSIZE - (p - IObuff),
5366 _("%lld characters"), (varnumber_T)nchars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005367 }
5368}
5369
5370/*
5371 * Append message for missing line separator to IObuff.
5372 */
5373 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005374msg_add_eol(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005375{
5376 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
5377}
5378
5379/*
5380 * Check modification time of file, before writing to it.
5381 * The size isn't checked, because using a tool like "gzip" takes care of
5382 * using the same timestamp but can't set the size.
5383 */
5384 static int
Bram Moolenaar8767f522016-07-01 17:17:39 +02005385check_mtime(buf_T *buf, stat_T *st)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005386{
5387 if (buf->b_mtime_read != 0
5388 && time_differs((long)st->st_mtime, buf->b_mtime_read))
5389 {
5390 msg_scroll = TRUE; /* don't overwrite messages here */
5391 msg_silent = 0; /* must give this prompt */
5392 /* don't use emsg() here, don't want to flush the buffers */
5393 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
Bram Moolenaar8820b482017-03-16 17:23:31 +01005394 HL_ATTR(HLF_E));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005395 if (ask_yesno((char_u *)_("Do you really want to write to it"),
5396 TRUE) == 'n')
5397 return FAIL;
5398 msg_scroll = FALSE; /* always overwrite the file message now */
5399 }
5400 return OK;
5401}
5402
5403 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005404time_differs(long t1, long t2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005405{
Bram Moolenaar48e330a2016-02-23 14:53:34 +01005406#if defined(__linux__) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
5408 * the seconds. Since the roundoff is done when flushing the inode, the
5409 * time may change unexpectedly by one second!!! */
5410 return (t1 - t2 > 1 || t2 - t1 > 1);
5411#else
5412 return (t1 != t2);
5413#endif
5414}
5415
5416/*
5417 * Call write() to write a number of bytes to the file.
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005418 * Handles encryption and 'encoding' conversion.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005419 *
5420 * Return FAIL for failure, OK otherwise.
5421 */
5422 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005423buf_write_bytes(struct bw_info *ip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424{
5425 int wlen;
5426 char_u *buf = ip->bw_buf; /* data to write */
5427 int len = ip->bw_len; /* length of data */
5428#ifdef HAS_BW_FLAGS
5429 int flags = ip->bw_flags; /* extra flags */
5430#endif
5431
5432#ifdef FEAT_MBYTE
5433 /*
5434 * Skip conversion when writing the crypt magic number or the BOM.
5435 */
5436 if (!(flags & FIO_NOCONVERT))
5437 {
5438 char_u *p;
5439 unsigned c;
5440 int n;
5441
5442 if (flags & FIO_UTF8)
5443 {
5444 /*
5445 * Convert latin1 in the buffer to UTF-8 in the file.
5446 */
5447 p = ip->bw_conv_buf; /* translate to buffer */
5448 for (wlen = 0; wlen < len; ++wlen)
5449 p += utf_char2bytes(buf[wlen], p);
5450 buf = ip->bw_conv_buf;
5451 len = (int)(p - ip->bw_conv_buf);
5452 }
5453 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
5454 {
5455 /*
5456 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
5457 * Latin1 chars in the file.
5458 */
5459 if (flags & FIO_LATIN1)
5460 p = buf; /* translate in-place (can only get shorter) */
5461 else
5462 p = ip->bw_conv_buf; /* translate to buffer */
5463 for (wlen = 0; wlen < len; wlen += n)
5464 {
5465 if (wlen == 0 && ip->bw_restlen != 0)
5466 {
5467 int l;
5468
5469 /* Use remainder of previous call. Append the start of
5470 * buf[] to get a full sequence. Might still be too
5471 * short! */
5472 l = CONV_RESTLEN - ip->bw_restlen;
5473 if (l > len)
5474 l = len;
5475 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005476 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005477 if (n > ip->bw_restlen + len)
5478 {
5479 /* We have an incomplete byte sequence at the end to
5480 * be written. We can't convert it without the
5481 * remaining bytes. Keep them for the next call. */
5482 if (ip->bw_restlen + len > CONV_RESTLEN)
5483 return FAIL;
5484 ip->bw_restlen += len;
5485 break;
5486 }
5487 if (n > 1)
5488 c = utf_ptr2char(ip->bw_rest);
5489 else
5490 c = ip->bw_rest[0];
5491 if (n >= ip->bw_restlen)
5492 {
5493 n -= ip->bw_restlen;
5494 ip->bw_restlen = 0;
5495 }
5496 else
5497 {
5498 ip->bw_restlen -= n;
5499 mch_memmove(ip->bw_rest, ip->bw_rest + n,
5500 (size_t)ip->bw_restlen);
5501 n = 0;
5502 }
5503 }
5504 else
5505 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005506 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507 if (n > len - wlen)
5508 {
5509 /* We have an incomplete byte sequence at the end to
5510 * be written. We can't convert it without the
5511 * remaining bytes. Keep them for the next call. */
5512 if (len - wlen > CONV_RESTLEN)
5513 return FAIL;
5514 ip->bw_restlen = len - wlen;
5515 mch_memmove(ip->bw_rest, buf + wlen,
5516 (size_t)ip->bw_restlen);
5517 break;
5518 }
5519 if (n > 1)
5520 c = utf_ptr2char(buf + wlen);
5521 else
5522 c = buf[wlen];
5523 }
5524
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005525 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error)
5526 {
5527 ip->bw_conv_error = TRUE;
5528 ip->bw_conv_error_lnum = ip->bw_start_lnum;
5529 }
5530 if (c == NL)
5531 ++ip->bw_start_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005532 }
5533 if (flags & FIO_LATIN1)
5534 len = (int)(p - buf);
5535 else
5536 {
5537 buf = ip->bw_conv_buf;
5538 len = (int)(p - ip->bw_conv_buf);
5539 }
5540 }
5541
5542# ifdef WIN3264
5543 else if (flags & FIO_CODEPAGE)
5544 {
5545 /*
5546 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
5547 * codepage.
5548 */
5549 char_u *from;
5550 size_t fromlen;
5551 char_u *to;
5552 int u8c;
5553 BOOL bad = FALSE;
5554 int needed;
5555
5556 if (ip->bw_restlen > 0)
5557 {
5558 /* Need to concatenate the remainder of the previous call and
5559 * the bytes of the current call. Use the end of the
5560 * conversion buffer for this. */
5561 fromlen = len + ip->bw_restlen;
5562 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5563 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5564 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5565 }
5566 else
5567 {
5568 from = buf;
5569 fromlen = len;
5570 }
5571
5572 to = ip->bw_conv_buf;
5573 if (enc_utf8)
5574 {
5575 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
5576 * The buffer has been allocated to be big enough. */
5577 while (fromlen > 0)
5578 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005579 n = (int)utf_ptr2len_len(from, (int)fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580 if (n > (int)fromlen) /* incomplete byte sequence */
5581 break;
5582 u8c = utf_ptr2char(from);
5583 *to++ = (u8c & 0xff);
5584 *to++ = (u8c >> 8);
5585 fromlen -= n;
5586 from += n;
5587 }
5588
5589 /* Copy remainder to ip->bw_rest[] to be used for the next
5590 * call. */
5591 if (fromlen > CONV_RESTLEN)
5592 {
5593 /* weird overlong sequence */
5594 ip->bw_conv_error = TRUE;
5595 return FAIL;
5596 }
5597 mch_memmove(ip->bw_rest, from, fromlen);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005598 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005599 }
5600 else
5601 {
5602 /* Convert from enc_codepage to UCS-2, to the start of the
5603 * buffer. The buffer has been allocated to be big enough. */
5604 ip->bw_restlen = 0;
5605 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005606 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005607 NULL, 0);
5608 if (needed == 0)
5609 {
5610 /* When conversion fails there may be a trailing byte. */
5611 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005612 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 NULL, 0);
5614 if (needed == 0)
5615 {
5616 /* Conversion doesn't work. */
5617 ip->bw_conv_error = TRUE;
5618 return FAIL;
5619 }
5620 /* Save the trailing byte for the next call. */
5621 ip->bw_rest[0] = from[fromlen - 1];
5622 ip->bw_restlen = 1;
5623 }
5624 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005625 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005626 (LPWSTR)to, needed);
5627 if (needed == 0)
5628 {
5629 /* Safety check: Conversion doesn't work. */
5630 ip->bw_conv_error = TRUE;
5631 return FAIL;
5632 }
5633 to += needed * 2;
5634 }
5635
5636 fromlen = to - ip->bw_conv_buf;
5637 buf = to;
5638# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5639 if (FIO_GET_CP(flags) == CP_UTF8)
5640 {
5641 /* Convert from UCS-2 to UTF-8, using the remainder of the
5642 * conversion buffer. Fails when out of space. */
5643 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
5644 {
5645 u8c = *from++;
5646 u8c += (*from++ << 8);
5647 to += utf_char2bytes(u8c, to);
5648 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
5649 {
5650 ip->bw_conv_error = TRUE;
5651 return FAIL;
5652 }
5653 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005654 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005655 }
5656 else
5657#endif
5658 {
5659 /* Convert from UCS-2 to the codepage, using the remainder of
5660 * the conversion buffer. If the conversion uses the default
5661 * character "0", the data doesn't fit in this encoding, so
5662 * fail. */
5663 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5664 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005665 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0,
5666 &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005667 if (bad)
5668 {
5669 ip->bw_conv_error = TRUE;
5670 return FAIL;
5671 }
5672 }
5673 }
5674# endif
5675
Bram Moolenaar56718732006-03-15 22:53:57 +00005676# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005677 else if (flags & FIO_MACROMAN)
5678 {
5679 /*
5680 * Convert UTF-8 or latin1 to Apple MacRoman.
5681 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005682 char_u *from;
5683 size_t fromlen;
5684
5685 if (ip->bw_restlen > 0)
5686 {
5687 /* Need to concatenate the remainder of the previous call and
5688 * the bytes of the current call. Use the end of the
5689 * conversion buffer for this. */
5690 fromlen = len + ip->bw_restlen;
5691 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5692 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5693 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5694 }
5695 else
5696 {
5697 from = buf;
5698 fromlen = len;
5699 }
5700
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005701 if (enc2macroman(from, fromlen,
5702 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5703 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005704 {
5705 ip->bw_conv_error = TRUE;
5706 return FAIL;
5707 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005708 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005709 }
5710# endif
5711
5712# ifdef USE_ICONV
5713 if (ip->bw_iconv_fd != (iconv_t)-1)
5714 {
5715 const char *from;
5716 size_t fromlen;
5717 char *to;
5718 size_t tolen;
5719
5720 /* Convert with iconv(). */
5721 if (ip->bw_restlen > 0)
5722 {
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005723 char *fp;
5724
Bram Moolenaar071d4272004-06-13 20:20:40 +00005725 /* Need to concatenate the remainder of the previous call and
5726 * the bytes of the current call. Use the end of the
5727 * conversion buffer for this. */
5728 fromlen = len + ip->bw_restlen;
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005729 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5730 mch_memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
5731 mch_memmove(fp + ip->bw_restlen, buf, (size_t)len);
5732 from = fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005733 tolen = ip->bw_conv_buflen - fromlen;
5734 }
5735 else
5736 {
5737 from = (const char *)buf;
5738 fromlen = len;
5739 tolen = ip->bw_conv_buflen;
5740 }
5741 to = (char *)ip->bw_conv_buf;
5742
5743 if (ip->bw_first)
5744 {
5745 size_t save_len = tolen;
5746
5747 /* output the initial shift state sequence */
5748 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5749
5750 /* There is a bug in iconv() on Linux (which appears to be
5751 * wide-spread) which sets "to" to NULL and messes up "tolen".
5752 */
5753 if (to == NULL)
5754 {
5755 to = (char *)ip->bw_conv_buf;
5756 tolen = save_len;
5757 }
5758 ip->bw_first = FALSE;
5759 }
5760
5761 /*
5762 * If iconv() has an error or there is not enough room, fail.
5763 */
5764 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5765 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5766 || fromlen > CONV_RESTLEN)
5767 {
5768 ip->bw_conv_error = TRUE;
5769 return FAIL;
5770 }
5771
5772 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5773 if (fromlen > 0)
5774 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5775 ip->bw_restlen = (int)fromlen;
5776
5777 buf = ip->bw_conv_buf;
5778 len = (int)((char_u *)to - ip->bw_conv_buf);
5779 }
5780# endif
5781 }
5782#endif /* FEAT_MBYTE */
5783
Bram Moolenaare6bf6552017-06-27 22:11:51 +02005784 if (ip->bw_fd < 0)
5785 /* Only checking conversion, which is OK if we get here. */
5786 return OK;
5787
Bram Moolenaar071d4272004-06-13 20:20:40 +00005788#ifdef FEAT_CRYPT
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02005789 if (flags & FIO_ENCRYPTED)
5790 {
5791 /* Encrypt the data. Do it in-place if possible, otherwise use an
5792 * allocated buffer. */
5793 if (crypt_works_inplace(ip->bw_buffer->b_cryptstate))
5794 {
5795 crypt_encode_inplace(ip->bw_buffer->b_cryptstate, buf, len);
5796 }
5797 else
5798 {
5799 char_u *outbuf;
5800
5801 len = crypt_encode_alloc(curbuf->b_cryptstate, buf, len, &outbuf);
5802 if (len == 0)
5803 return OK; /* Crypt layer is buffering, will flush later. */
5804 wlen = write_eintr(ip->bw_fd, outbuf, len);
5805 vim_free(outbuf);
5806 return (wlen < len) ? FAIL : OK;
5807 }
5808 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005809#endif
5810
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005811 wlen = write_eintr(ip->bw_fd, buf, len);
5812 return (wlen < len) ? FAIL : OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813}
5814
5815#ifdef FEAT_MBYTE
5816/*
5817 * Convert a Unicode character to bytes.
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005818 * Return TRUE for an error, FALSE when it's OK.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005819 */
5820 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005821ucs2bytes(
5822 unsigned c, /* in: character */
5823 char_u **pp, /* in/out: pointer to result */
5824 int flags) /* FIO_ flags */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005825{
5826 char_u *p = *pp;
5827 int error = FALSE;
5828 int cc;
5829
5830
5831 if (flags & FIO_UCS4)
5832 {
5833 if (flags & FIO_ENDIAN_L)
5834 {
5835 *p++ = c;
5836 *p++ = (c >> 8);
5837 *p++ = (c >> 16);
5838 *p++ = (c >> 24);
5839 }
5840 else
5841 {
5842 *p++ = (c >> 24);
5843 *p++ = (c >> 16);
5844 *p++ = (c >> 8);
5845 *p++ = c;
5846 }
5847 }
5848 else if (flags & (FIO_UCS2 | FIO_UTF16))
5849 {
5850 if (c >= 0x10000)
5851 {
5852 if (flags & FIO_UTF16)
5853 {
5854 /* Make two words, ten bits of the character in each. First
5855 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5856 c -= 0x10000;
5857 if (c >= 0x100000)
5858 error = TRUE;
5859 cc = ((c >> 10) & 0x3ff) + 0xd800;
5860 if (flags & FIO_ENDIAN_L)
5861 {
5862 *p++ = cc;
5863 *p++ = ((unsigned)cc >> 8);
5864 }
5865 else
5866 {
5867 *p++ = ((unsigned)cc >> 8);
5868 *p++ = cc;
5869 }
5870 c = (c & 0x3ff) + 0xdc00;
5871 }
5872 else
5873 error = TRUE;
5874 }
5875 if (flags & FIO_ENDIAN_L)
5876 {
5877 *p++ = c;
5878 *p++ = (c >> 8);
5879 }
5880 else
5881 {
5882 *p++ = (c >> 8);
5883 *p++ = c;
5884 }
5885 }
5886 else /* Latin1 */
5887 {
5888 if (c >= 0x100)
5889 {
5890 error = TRUE;
5891 *p++ = 0xBF;
5892 }
5893 else
5894 *p++ = c;
5895 }
5896
5897 *pp = p;
5898 return error;
5899}
5900
5901/*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005902 * Return TRUE if file encoding "fenc" requires conversion from or to
5903 * 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005904 */
5905 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005906need_conversion(char_u *fenc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005907{
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005908 int same_encoding;
5909 int enc_flags;
5910 int fenc_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005911
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005912 if (*fenc == NUL || STRCMP(p_enc, fenc) == 0)
Bram Moolenaar442b4222010-05-24 21:34:22 +02005913 {
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005914 same_encoding = TRUE;
Bram Moolenaar442b4222010-05-24 21:34:22 +02005915 fenc_flags = 0;
5916 }
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005917 else
5918 {
5919 /* Ignore difference between "ansi" and "latin1", "ucs-4" and
5920 * "ucs-4be", etc. */
5921 enc_flags = get_fio_flags(p_enc);
5922 fenc_flags = get_fio_flags(fenc);
5923 same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
5924 }
5925 if (same_encoding)
5926 {
5927 /* Specified encoding matches with 'encoding'. This requires
5928 * conversion when 'encoding' is Unicode but not UTF-8. */
5929 return enc_unicode != 0;
5930 }
5931
5932 /* Encodings differ. However, conversion is not needed when 'enc' is any
5933 * Unicode encoding and the file is UTF-8. */
5934 return !(enc_utf8 && fenc_flags == FIO_UTF8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005935}
5936
5937/*
5938 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5939 * internal conversion.
5940 * if "ptr" is an empty string, use 'encoding'.
5941 */
5942 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005943get_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005944{
5945 int prop;
5946
5947 if (*ptr == NUL)
5948 ptr = p_enc;
5949
5950 prop = enc_canon_props(ptr);
5951 if (prop & ENC_UNICODE)
5952 {
5953 if (prop & ENC_2BYTE)
5954 {
5955 if (prop & ENC_ENDIAN_L)
5956 return FIO_UCS2 | FIO_ENDIAN_L;
5957 return FIO_UCS2;
5958 }
5959 if (prop & ENC_4BYTE)
5960 {
5961 if (prop & ENC_ENDIAN_L)
5962 return FIO_UCS4 | FIO_ENDIAN_L;
5963 return FIO_UCS4;
5964 }
5965 if (prop & ENC_2WORD)
5966 {
5967 if (prop & ENC_ENDIAN_L)
5968 return FIO_UTF16 | FIO_ENDIAN_L;
5969 return FIO_UTF16;
5970 }
5971 return FIO_UTF8;
5972 }
5973 if (prop & ENC_LATIN1)
5974 return FIO_LATIN1;
5975 /* must be ENC_DBCS, requires iconv() */
5976 return 0;
5977}
5978
5979#ifdef WIN3264
5980/*
5981 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5982 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5983 * Used for conversion between 'encoding' and 'fileencoding'.
5984 */
5985 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01005986get_win_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005987{
5988 int cp;
5989
5990 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5991 if (!enc_utf8 && enc_codepage <= 0)
5992 return 0;
5993
5994 cp = encname2codepage(ptr);
5995 if (cp == 0)
5996 {
5997# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5998 if (STRCMP(ptr, "utf-8") == 0)
5999 cp = CP_UTF8;
6000 else
6001# endif
6002 return 0;
6003 }
6004 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
6005}
6006#endif
6007
Bram Moolenaard0573012017-10-28 21:11:06 +02006008#ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00006009/*
6010 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
6011 * needed for the internal conversion to/from utf-8 or latin1.
6012 */
6013 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006014get_mac_fio_flags(char_u *ptr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006015{
6016 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
6017 && (enc_canon_props(ptr) & ENC_MACROMAN))
6018 return FIO_MACROMAN;
6019 return 0;
6020}
6021#endif
6022
6023/*
6024 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
6025 * "size" must be at least 2.
6026 * Return the name of the encoding and set "*lenp" to the length.
6027 * Returns NULL when no BOM found.
6028 */
6029 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006030check_for_bom(
6031 char_u *p,
6032 long size,
6033 int *lenp,
6034 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006035{
6036 char *name = NULL;
6037 int len = 2;
6038
6039 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
Bram Moolenaaree0f5a62008-07-24 20:09:16 +00006040 && (flags == FIO_ALL || flags == FIO_UTF8 || flags == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041 {
6042 name = "utf-8"; /* EF BB BF */
6043 len = 3;
6044 }
6045 else if (p[0] == 0xff && p[1] == 0xfe)
6046 {
6047 if (size >= 4 && p[2] == 0 && p[3] == 0
6048 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
6049 {
6050 name = "ucs-4le"; /* FF FE 00 00 */
6051 len = 4;
6052 }
Bram Moolenaar223a1892008-11-11 20:57:11 +00006053 else if (flags == (FIO_UCS2 | FIO_ENDIAN_L))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054 name = "ucs-2le"; /* FF FE */
Bram Moolenaar223a1892008-11-11 20:57:11 +00006055 else if (flags == FIO_ALL || flags == (FIO_UTF16 | FIO_ENDIAN_L))
6056 /* utf-16le is preferred, it also works for ucs-2le text */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006057 name = "utf-16le"; /* FF FE */
6058 }
6059 else if (p[0] == 0xfe && p[1] == 0xff
6060 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
6061 {
Bram Moolenaarffd82c52008-02-20 17:15:26 +00006062 /* Default to utf-16, it works also for ucs-2 text. */
6063 if (flags == FIO_UCS2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006064 name = "ucs-2"; /* FE FF */
Bram Moolenaarffd82c52008-02-20 17:15:26 +00006065 else
6066 name = "utf-16"; /* FE FF */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006067 }
6068 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
6069 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
6070 {
6071 name = "ucs-4"; /* 00 00 FE FF */
6072 len = 4;
6073 }
6074
6075 *lenp = len;
6076 return (char_u *)name;
6077}
6078
6079/*
6080 * Generate a BOM in "buf[4]" for encoding "name".
6081 * Return the length of the BOM (zero when no BOM).
6082 */
6083 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006084make_bom(char_u *buf, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006085{
6086 int flags;
6087 char_u *p;
6088
6089 flags = get_fio_flags(name);
6090
6091 /* Can't put a BOM in a non-Unicode file. */
6092 if (flags == FIO_LATIN1 || flags == 0)
6093 return 0;
6094
6095 if (flags == FIO_UTF8) /* UTF-8 */
6096 {
6097 buf[0] = 0xef;
6098 buf[1] = 0xbb;
6099 buf[2] = 0xbf;
6100 return 3;
6101 }
6102 p = buf;
6103 (void)ucs2bytes(0xfeff, &p, flags);
6104 return (int)(p - buf);
6105}
6106#endif
6107
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00006108#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \
Bram Moolenaara0174af2008-01-02 20:08:25 +00006109 defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006110/*
6111 * Try to find a shortname by comparing the fullname with the current
6112 * directory.
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006113 * Returns "full_path" or pointer into "full_path" if shortened.
6114 */
6115 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006116shorten_fname1(char_u *full_path)
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006117{
Bram Moolenaard9462e32011-04-11 21:35:11 +02006118 char_u *dirname;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006119 char_u *p = full_path;
6120
Bram Moolenaard9462e32011-04-11 21:35:11 +02006121 dirname = alloc(MAXPATHL);
6122 if (dirname == NULL)
6123 return full_path;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006124 if (mch_dirname(dirname, MAXPATHL) == OK)
6125 {
6126 p = shorten_fname(full_path, dirname);
6127 if (p == NULL || *p == NUL)
6128 p = full_path;
6129 }
Bram Moolenaard9462e32011-04-11 21:35:11 +02006130 vim_free(dirname);
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006131 return p;
6132}
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00006133#endif
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006134
6135/*
6136 * Try to find a shortname by comparing the fullname with the current
6137 * directory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006138 * Returns NULL if not shorter name possible, pointer into "full_path"
6139 * otherwise.
6140 */
6141 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006142shorten_fname(char_u *full_path, char_u *dir_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006143{
6144 int len;
6145 char_u *p;
6146
6147 if (full_path == NULL)
6148 return NULL;
6149 len = (int)STRLEN(dir_name);
6150 if (fnamencmp(dir_name, full_path, len) == 0)
6151 {
6152 p = full_path + len;
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006153#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006154 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006155 * MSWIN: when a file is in the root directory, dir_name will end in a
Bram Moolenaar071d4272004-06-13 20:20:40 +00006156 * slash, since C: by itself does not define a specific dir. In this
6157 * case p may already be correct. <negri>
6158 */
6159 if (!((len > 2) && (*(p - 2) == ':')))
6160#endif
6161 {
6162 if (vim_ispathsep(*p))
6163 ++p;
6164#ifndef VMS /* the path separator is always part of the path */
6165 else
6166 p = NULL;
6167#endif
6168 }
6169 }
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006170#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006171 /*
6172 * When using a file in the current drive, remove the drive name:
6173 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
6174 * a floppy from "A:\dir" to "B:\dir".
6175 */
6176 else if (len > 3
6177 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
6178 && full_path[1] == ':'
6179 && vim_ispathsep(full_path[2]))
6180 p = full_path + 2;
6181#endif
6182 else
6183 p = NULL;
6184 return p;
6185}
6186
6187/*
6188 * Shorten filenames for all buffers.
6189 * When "force" is TRUE: Use full path from now on for files currently being
6190 * edited, both for file name and swap file name. Try to shorten the file
6191 * names a bit, if safe to do so.
6192 * When "force" is FALSE: Only try to shorten absolute file names.
6193 * For buffers that have buftype "nofile" or "scratch": never change the file
6194 * name.
6195 */
6196 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006197shorten_fnames(int force)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006198{
6199 char_u dirname[MAXPATHL];
6200 buf_T *buf;
6201 char_u *p;
6202
6203 mch_dirname(dirname, MAXPATHL);
Bram Moolenaar29323592016-07-24 22:04:11 +02006204 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006205 {
6206 if (buf->b_fname != NULL
6207#ifdef FEAT_QUICKFIX
6208 && !bt_nofile(buf)
6209#endif
6210 && !path_with_url(buf->b_fname)
6211 && (force
6212 || buf->b_sfname == NULL
6213 || mch_isFullName(buf->b_sfname)))
6214 {
Bram Moolenaard23a8232018-02-10 18:45:26 +01006215 VIM_CLEAR(buf->b_sfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006216 p = shorten_fname(buf->b_ffname, dirname);
6217 if (p != NULL)
6218 {
6219 buf->b_sfname = vim_strsave(p);
6220 buf->b_fname = buf->b_sfname;
6221 }
6222 if (p == NULL || buf->b_fname == NULL)
6223 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006224 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006225
6226 /* Always make the swap file name a full path, a "nofile" buffer may
6227 * also have a swap file. */
6228 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006229 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006230 status_redraw_all();
Bram Moolenaar49d7bf12006-02-17 21:45:41 +00006231 redraw_tabline = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006232}
6233
6234#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
6235 || defined(FEAT_GUI_MSWIN) \
6236 || defined(FEAT_GUI_MAC) \
6237 || defined(PROTO)
6238/*
6239 * Shorten all filenames in "fnames[count]" by current directory.
6240 */
6241 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006242shorten_filenames(char_u **fnames, int count)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006243{
6244 int i;
6245 char_u dirname[MAXPATHL];
6246 char_u *p;
6247
6248 if (fnames == NULL || count < 1)
6249 return;
6250 mch_dirname(dirname, sizeof(dirname));
6251 for (i = 0; i < count; ++i)
6252 {
6253 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
6254 {
6255 /* shorten_fname() returns pointer in given "fnames[i]". If free
6256 * "fnames[i]" first, "p" becomes invalid. So we need to copy
6257 * "p" first then free fnames[i]. */
6258 p = vim_strsave(p);
6259 vim_free(fnames[i]);
6260 fnames[i] = p;
6261 }
6262 }
6263}
6264#endif
6265
6266/*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006267 * add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
Bram Moolenaar071d4272004-06-13 20:20:40 +00006268 * fo_o_h.ext for MSDOS or when shortname option set.
6269 *
6270 * Assumed that fname is a valid name found in the filesystem we assure that
6271 * the return value is a different name and ends in 'ext'.
6272 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
6273 * characters otherwise.
6274 * Space for the returned name is allocated, must be freed later.
6275 * Returns NULL when out of memory.
6276 */
6277 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006278modname(
6279 char_u *fname,
6280 char_u *ext,
6281 int prepend_dot) /* may prepend a '.' to file name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006282{
Bram Moolenaar48e330a2016-02-23 14:53:34 +01006283 return buf_modname((curbuf->b_p_sn || curbuf->b_shortname),
Bram Moolenaar071d4272004-06-13 20:20:40 +00006284 fname, ext, prepend_dot);
6285}
6286
6287 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006288buf_modname(
6289 int shortname, /* use 8.3 file name */
6290 char_u *fname,
6291 char_u *ext,
6292 int prepend_dot) /* may prepend a '.' to file name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006293{
6294 char_u *retval;
6295 char_u *s;
6296 char_u *e;
6297 char_u *ptr;
6298 int fnamelen, extlen;
6299
6300 extlen = (int)STRLEN(ext);
6301
6302 /*
6303 * If there is no file name we must get the name of the current directory
6304 * (we need the full path in case :cd is used).
6305 */
6306 if (fname == NULL || *fname == NUL)
6307 {
6308 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
6309 if (retval == NULL)
6310 return NULL;
6311 if (mch_dirname(retval, MAXPATHL) == FAIL ||
6312 (fnamelen = (int)STRLEN(retval)) == 0)
6313 {
6314 vim_free(retval);
6315 return NULL;
6316 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006317 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006318 {
6319 retval[fnamelen++] = PATHSEP;
6320 retval[fnamelen] = NUL;
6321 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006322 prepend_dot = FALSE; /* nothing to prepend a dot to */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006323 }
6324 else
6325 {
6326 fnamelen = (int)STRLEN(fname);
6327 retval = alloc((unsigned)(fnamelen + extlen + 3));
6328 if (retval == NULL)
6329 return NULL;
6330 STRCPY(retval, fname);
6331#ifdef VMS
6332 vms_remove_version(retval); /* we do not need versions here */
6333#endif
6334 }
6335
6336 /*
6337 * search backwards until we hit a '/', '\' or ':' replacing all '.'
6338 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
6339 * Then truncate what is after the '/', '\' or ':' to 8 characters for
6340 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
6341 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006342 for (ptr = retval + fnamelen; ptr > retval; MB_PTR_BACK(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006343 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006344 if (*ext == '.'
Bram Moolenaare60acc12011-05-10 16:41:25 +02006345#ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006346 && (!USE_LONG_FNAME || shortname)
Bram Moolenaare60acc12011-05-10 16:41:25 +02006347#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006348 && shortname
Bram Moolenaare60acc12011-05-10 16:41:25 +02006349#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006350 )
6351 if (*ptr == '.') /* replace '.' by '_' */
6352 *ptr = '_';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006353 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006354 {
6355 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006356 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006357 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006358 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006359
6360 /* the file name has at most BASENAMELEN characters. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006361 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
6362 ptr[BASENAMELEN] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006363
6364 s = ptr + STRLEN(ptr);
6365
6366 /*
6367 * For 8.3 file names we may have to reduce the length.
6368 */
6369#ifdef USE_LONG_FNAME
6370 if (!USE_LONG_FNAME || shortname)
6371#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006372 if (shortname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006373#endif
6374 {
6375 /*
6376 * If there is no file name, or the file name ends in '/', and the
6377 * extension starts with '.', put a '_' before the dot, because just
6378 * ".ext" is invalid.
6379 */
6380 if (fname == NULL || *fname == NUL
6381 || vim_ispathsep(fname[STRLEN(fname) - 1]))
6382 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006383 if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006384 *s++ = '_';
6385 }
6386 /*
6387 * If the extension starts with '.', truncate the base name at 8
6388 * characters
6389 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006390 else if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006391 {
Bram Moolenaar78a15312009-05-15 19:33:18 +00006392 if ((size_t)(s - ptr) > (size_t)8)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006393 {
6394 s = ptr + 8;
6395 *s = '\0';
6396 }
6397 }
6398 /*
6399 * If the extension doesn't start with '.', and the file name
6400 * doesn't have an extension yet, append a '.'
6401 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006402 else if ((e = vim_strchr(ptr, '.')) == NULL)
6403 *s++ = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006404 /*
6405 * If the extension doesn't start with '.', and there already is an
Bram Moolenaar7263a772007-05-10 17:35:54 +00006406 * extension, it may need to be truncated
Bram Moolenaar071d4272004-06-13 20:20:40 +00006407 */
6408 else if ((int)STRLEN(e) + extlen > 4)
6409 s = e + 4 - extlen;
6410 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +01006411#if defined(USE_LONG_FNAME) || defined(WIN3264)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006412 /*
6413 * If there is no file name, and the extension starts with '.', put a
6414 * '_' before the dot, because just ".ext" may be invalid if it's on a
6415 * FAT partition, and on HPFS it doesn't matter.
6416 */
6417 else if ((fname == NULL || *fname == NUL) && *ext == '.')
6418 *s++ = '_';
6419#endif
6420
6421 /*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006422 * Append the extension.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006423 * ext can start with '.' and cannot exceed 3 more characters.
6424 */
6425 STRCPY(s, ext);
6426
Bram Moolenaar071d4272004-06-13 20:20:40 +00006427 /*
6428 * Prepend the dot.
6429 */
Bram Moolenaare60acc12011-05-10 16:41:25 +02006430 if (prepend_dot && !shortname && *(e = gettail(retval)) != '.'
Bram Moolenaar071d4272004-06-13 20:20:40 +00006431#ifdef USE_LONG_FNAME
6432 && USE_LONG_FNAME
6433#endif
6434 )
6435 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006436 STRMOVE(e + 1, e);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006437 *e = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006438 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006439
6440 /*
6441 * Check that, after appending the extension, the file name is really
6442 * different.
6443 */
6444 if (fname != NULL && STRCMP(fname, retval) == 0)
6445 {
6446 /* we search for a character that can be replaced by '_' */
6447 while (--s >= ptr)
6448 {
6449 if (*s != '_')
6450 {
6451 *s = '_';
6452 break;
6453 }
6454 }
6455 if (s < ptr) /* fname was "________.<ext>", how tricky! */
6456 *ptr = 'v';
6457 }
6458 return retval;
6459}
6460
6461/*
6462 * Like fgets(), but if the file line is too long, it is truncated and the
6463 * rest of the line is thrown away. Returns TRUE for end-of-file.
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01006464 * If the line is truncated then buf[size - 2] will not be NUL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006465 */
6466 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006467vim_fgets(char_u *buf, int size, FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006468{
6469 char *eof;
6470#define FGETS_SIZE 200
6471 char tbuf[FGETS_SIZE];
6472
6473 buf[size - 2] = NUL;
6474#ifdef USE_CR
6475 eof = fgets_cr((char *)buf, size, fp);
6476#else
6477 eof = fgets((char *)buf, size, fp);
6478#endif
6479 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
6480 {
6481 buf[size - 1] = NUL; /* Truncate the line */
6482
6483 /* Now throw away the rest of the line: */
6484 do
6485 {
6486 tbuf[FGETS_SIZE - 2] = NUL;
6487#ifdef USE_CR
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006488 ignoredp = fgets_cr((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006489#else
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006490 ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006491#endif
6492 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
6493 }
6494 return (eof == NULL);
6495}
6496
6497#if defined(USE_CR) || defined(PROTO)
6498/*
6499 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
6500 * Returns TRUE for end-of-file.
6501 * Only used for the Mac, because it's much slower than vim_fgets().
6502 */
6503 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006504tag_fgets(char_u *buf, int size, FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006505{
6506 int i = 0;
6507 int c;
6508 int eof = FALSE;
6509
6510 for (;;)
6511 {
6512 c = fgetc(fp);
6513 if (c == EOF)
6514 {
6515 eof = TRUE;
6516 break;
6517 }
6518 if (c == '\r')
6519 {
6520 /* Always store a NL for end-of-line. */
6521 if (i < size - 1)
6522 buf[i++] = '\n';
6523 c = fgetc(fp);
6524 if (c != '\n') /* Macintosh format: single CR. */
6525 ungetc(c, fp);
6526 break;
6527 }
6528 if (i < size - 1)
6529 buf[i++] = c;
6530 if (c == '\n')
6531 break;
6532 }
6533 buf[i] = NUL;
6534 return eof;
6535}
6536#endif
6537
6538/*
6539 * rename() only works if both files are on the same file system, this
6540 * function will (attempts to?) copy the file across if rename fails -- webb
6541 * Return -1 for failure, 0 for success.
6542 */
6543 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006544vim_rename(char_u *from, char_u *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006545{
6546 int fd_in;
6547 int fd_out;
6548 int n;
6549 char *errmsg = NULL;
6550 char *buffer;
6551#ifdef AMIGA
6552 BPTR flock;
6553#endif
Bram Moolenaar8767f522016-07-01 17:17:39 +02006554 stat_T st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006555 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006556#ifdef HAVE_ACL
6557 vim_acl_T acl; /* ACL from original file */
6558#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006559 int use_tmp_file = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006560
6561 /*
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006562 * When the names are identical, there is nothing to do. When they refer
6563 * to the same file (ignoring case and slash/backslash differences) but
6564 * the file name differs we need to go through a temp file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006565 */
6566 if (fnamecmp(from, to) == 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006567 {
Bram Moolenaar71afbfe2013-03-19 16:49:16 +01006568 if (p_fic && STRCMP(gettail(from), gettail(to)) != 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006569 use_tmp_file = TRUE;
6570 else
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006571 return 0;
6572 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006573
6574 /*
6575 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
6576 */
6577 if (mch_stat((char *)from, &st) < 0)
6578 return -1;
6579
Bram Moolenaar3576da72008-12-30 15:15:57 +00006580#ifdef UNIX
6581 {
Bram Moolenaar8767f522016-07-01 17:17:39 +02006582 stat_T st_to;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006583
6584 /* It's possible for the source and destination to be the same file.
6585 * This happens when "from" and "to" differ in case and are on a FAT32
6586 * filesystem. In that case go through a temp file name. */
6587 if (mch_stat((char *)to, &st_to) >= 0
6588 && st.st_dev == st_to.st_dev
6589 && st.st_ino == st_to.st_ino)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006590 use_tmp_file = TRUE;
6591 }
6592#endif
Bram Moolenaar1c32dff2011-05-05 16:41:24 +02006593#ifdef WIN3264
6594 {
6595 BY_HANDLE_FILE_INFORMATION info1, info2;
6596
6597 /* It's possible for the source and destination to be the same file.
6598 * In that case go through a temp file name. This makes rename("foo",
6599 * "./foo") a no-op (in a complicated way). */
6600 if (win32_fileinfo(from, &info1) == FILEINFO_OK
6601 && win32_fileinfo(to, &info2) == FILEINFO_OK
6602 && info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
6603 && info1.nFileIndexHigh == info2.nFileIndexHigh
6604 && info1.nFileIndexLow == info2.nFileIndexLow)
6605 use_tmp_file = TRUE;
6606 }
6607#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006608
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006609 if (use_tmp_file)
6610 {
6611 char tempname[MAXPATHL + 1];
6612
6613 /*
6614 * Find a name that doesn't exist and is in the same directory.
6615 * Rename "from" to "tempname" and then rename "tempname" to "to".
6616 */
6617 if (STRLEN(from) >= MAXPATHL - 5)
6618 return -1;
6619 STRCPY(tempname, from);
6620 for (n = 123; n < 99999; ++n)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006621 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006622 sprintf((char *)gettail((char_u *)tempname), "%d", n);
6623 if (mch_stat(tempname, &st) < 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006624 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006625 if (mch_rename((char *)from, tempname) == 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006626 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006627 if (mch_rename(tempname, (char *)to) == 0)
6628 return 0;
6629 /* Strange, the second step failed. Try moving the
6630 * file back and return failure. */
6631 mch_rename(tempname, (char *)from);
Bram Moolenaar3576da72008-12-30 15:15:57 +00006632 return -1;
6633 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006634 /* If it fails for one temp name it will most likely fail
6635 * for any temp name, give up. */
6636 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006637 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006638 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006639 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006640 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006641
Bram Moolenaar071d4272004-06-13 20:20:40 +00006642 /*
6643 * Delete the "to" file, this is required on some systems to make the
6644 * mch_rename() work, on other systems it makes sure that we don't have
6645 * two files when the mch_rename() fails.
6646 */
6647
6648#ifdef AMIGA
6649 /*
6650 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
6651 * that the name of the "to" file is the same as the "from" file, even
Bram Moolenaar7263a772007-05-10 17:35:54 +00006652 * though the names are different. To avoid the chance of accidentally
Bram Moolenaar071d4272004-06-13 20:20:40 +00006653 * deleting the "from" file (horror!) we lock it during the remove.
6654 *
6655 * When used for making a backup before writing the file: This should not
6656 * happen with ":w", because startscript() should detect this problem and
6657 * set buf->b_shortname, causing modname() to return a correct ".bak" file
6658 * name. This problem does exist with ":w filename", but then the
6659 * original file will be somewhere else so the backup isn't really
6660 * important. If autoscripting is off the rename may fail.
6661 */
6662 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
6663#endif
6664 mch_remove(to);
6665#ifdef AMIGA
6666 if (flock)
6667 UnLock(flock);
6668#endif
6669
6670 /*
6671 * First try a normal rename, return if it works.
6672 */
6673 if (mch_rename((char *)from, (char *)to) == 0)
6674 return 0;
6675
6676 /*
6677 * Rename() failed, try copying the file.
6678 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006679 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006680#ifdef HAVE_ACL
6681 /* For systems that support ACL: get the ACL from the original file. */
6682 acl = mch_get_acl(from);
6683#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006684 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
6685 if (fd_in == -1)
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006686 {
6687#ifdef HAVE_ACL
6688 mch_free_acl(acl);
6689#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006690 return -1;
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006691 }
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006692
6693 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00006694 fd_out = mch_open((char *)to,
6695 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696 if (fd_out == -1)
6697 {
6698 close(fd_in);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006699#ifdef HAVE_ACL
6700 mch_free_acl(acl);
6701#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006702 return -1;
6703 }
6704
6705 buffer = (char *)alloc(BUFSIZE);
6706 if (buffer == NULL)
6707 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006708 close(fd_out);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006709 close(fd_in);
6710#ifdef HAVE_ACL
6711 mch_free_acl(acl);
6712#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006713 return -1;
6714 }
6715
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01006716 while ((n = read_eintr(fd_in, buffer, BUFSIZE)) > 0)
6717 if (write_eintr(fd_out, buffer, n) != n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006718 {
6719 errmsg = _("E208: Error writing to \"%s\"");
6720 break;
6721 }
6722
6723 vim_free(buffer);
6724 close(fd_in);
6725 if (close(fd_out) < 0)
6726 errmsg = _("E209: Error closing \"%s\"");
6727 if (n < 0)
6728 {
6729 errmsg = _("E210: Error reading \"%s\"");
6730 to = from;
6731 }
Bram Moolenaar7263a772007-05-10 17:35:54 +00006732#ifndef UNIX /* for Unix mch_open() already set the permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006733 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00006734#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006735#ifdef HAVE_ACL
6736 mch_set_acl(to, acl);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006737 mch_free_acl(acl);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006738#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02006739#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaare8747442013-11-12 18:09:29 +01006740 mch_copy_sec(from, to);
Bram Moolenaar0671de32013-11-12 05:12:03 +01006741#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006742 if (errmsg != NULL)
6743 {
6744 EMSG2(errmsg, to);
6745 return -1;
6746 }
6747 mch_remove(from);
6748 return 0;
6749}
6750
6751static int already_warned = FALSE;
6752
6753/*
6754 * Check if any not hidden buffer has been changed.
6755 * Postpone the check if there are characters in the stuff buffer, a global
6756 * command is being executed, a mapping is being executed or an autocommand is
6757 * busy.
6758 * Returns TRUE if some message was written (screen should be redrawn and
6759 * cursor positioned).
6760 */
6761 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006762check_timestamps(
6763 int focus) /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006764{
6765 buf_T *buf;
6766 int didit = 0;
6767 int n;
6768
6769 /* Don't check timestamps while system() or another low-level function may
6770 * cause us to lose and gain focus. */
6771 if (no_check_timestamps > 0)
6772 return FALSE;
6773
6774 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6775 * event and we would keep on checking if the file is steadily growing.
6776 * Do check again after typing something. */
6777 if (focus && did_check_timestamps)
6778 {
6779 need_check_timestamps = TRUE;
6780 return FALSE;
6781 }
6782
6783 if (!stuff_empty() || global_busy || !typebuf_typed()
6784#ifdef FEAT_AUTOCMD
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006785 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006786#endif
6787 )
6788 need_check_timestamps = TRUE; /* check later */
6789 else
6790 {
6791 ++no_wait_return;
6792 did_check_timestamps = TRUE;
6793 already_warned = FALSE;
Bram Moolenaar29323592016-07-24 22:04:11 +02006794 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006795 {
6796 /* Only check buffers in a window. */
6797 if (buf->b_nwindows > 0)
6798 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006799 bufref_T bufref;
6800
6801 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006802 n = buf_check_timestamp(buf, focus);
6803 if (didit < n)
6804 didit = n;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006805 if (n > 0 && !bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006806 {
6807 /* Autocommands have removed the buffer, start at the
6808 * first one again. */
6809 buf = firstbuf;
6810 continue;
6811 }
6812 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006813 }
6814 --no_wait_return;
6815 need_check_timestamps = FALSE;
6816 if (need_wait_return && didit == 2)
6817 {
6818 /* make sure msg isn't overwritten */
6819 msg_puts((char_u *)"\n");
6820 out_flush();
6821 }
6822 }
6823 return didit;
6824}
6825
6826/*
6827 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6828 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6829 * empty.
6830 */
6831 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006832move_lines(buf_T *frombuf, buf_T *tobuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006833{
6834 buf_T *tbuf = curbuf;
6835 int retval = OK;
6836 linenr_T lnum;
6837 char_u *p;
6838
6839 /* Copy the lines in "frombuf" to "tobuf". */
6840 curbuf = tobuf;
6841 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6842 {
6843 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6844 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6845 {
6846 vim_free(p);
6847 retval = FAIL;
6848 break;
6849 }
6850 vim_free(p);
6851 }
6852
6853 /* Delete all the lines in "frombuf". */
6854 if (retval != FAIL)
6855 {
6856 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006857 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6858 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006859 {
6860 /* Oops! We could try putting back the saved lines, but that
6861 * might fail again... */
6862 retval = FAIL;
6863 break;
6864 }
6865 }
6866
6867 curbuf = tbuf;
6868 return retval;
6869}
6870
6871/*
6872 * Check if buffer "buf" has been changed.
6873 * Also check if the file for a new buffer unexpectedly appeared.
6874 * return 1 if a changed buffer was found.
6875 * return 2 if a message has been displayed.
6876 * return 0 otherwise.
6877 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006878 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01006879buf_check_timestamp(
6880 buf_T *buf,
6881 int focus UNUSED) /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006882{
Bram Moolenaar8767f522016-07-01 17:17:39 +02006883 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006884 int stat_res;
6885 int retval = 0;
6886 char_u *path;
6887 char_u *tbuf;
6888 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006889 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006890 int helpmesg = FALSE;
6891 int reload = FALSE;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006892 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006893#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6894 int can_reload = FALSE;
6895#endif
Bram Moolenaar8767f522016-07-01 17:17:39 +02006896 off_T orig_size = buf->b_orig_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006897 int orig_mode = buf->b_orig_mode;
6898#ifdef FEAT_GUI
6899 int save_mouse_correct = need_mouse_correct;
6900#endif
6901#ifdef FEAT_AUTOCMD
6902 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006903 int n;
6904 char_u *s;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006905 bufref_T bufref;
6906
6907 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006908#endif
6909
6910 /* If there is no file name, the buffer is not loaded, 'buftype' is
6911 * set, we are in the middle of a save or being called recursively: ignore
6912 * this buffer. */
6913 if (buf->b_ffname == NULL
6914 || buf->b_ml.ml_mfp == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006915 || *buf->b_p_bt != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006916 || buf->b_saving
6917#ifdef FEAT_AUTOCMD
6918 || busy
6919#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006920#ifdef FEAT_NETBEANS_INTG
6921 || isNetbeansBuffer(buf)
6922#endif
Bram Moolenaar8cad9302017-08-12 14:32:32 +02006923#ifdef FEAT_TERMINAL
6924 || buf->b_term != NULL
6925#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006926 )
6927 return 0;
6928
6929 if ( !(buf->b_flags & BF_NOTEDITED)
6930 && buf->b_mtime != 0
6931 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6932 || time_differs((long)st.st_mtime, buf->b_mtime)
Bram Moolenaara7611f62014-05-02 15:46:14 +02006933 || st.st_size != buf->b_orig_size
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934#ifdef HAVE_ST_MODE
6935 || (int)st.st_mode != buf->b_orig_mode
6936#else
6937 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6938#endif
6939 ))
6940 {
6941 retval = 1;
6942
Bram Moolenaar316059c2006-01-14 21:18:42 +00006943 /* set b_mtime to stop further warnings (e.g., when executing
6944 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006945 if (stat_res < 0)
6946 {
6947 buf->b_mtime = 0;
6948 buf->b_orig_size = 0;
6949 buf->b_orig_mode = 0;
6950 }
6951 else
6952 buf_store_time(buf, &st, buf->b_ffname);
6953
6954 /* Don't do anything for a directory. Might contain the file
6955 * explorer. */
6956 if (mch_isdir(buf->b_fname))
6957 ;
6958
6959 /*
6960 * If 'autoread' is set, the buffer has no changes and the file still
6961 * exists, reload the buffer. Use the buffer-local option value if it
6962 * was set, the global option value otherwise.
6963 */
6964 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6965 && !bufIsChanged(buf) && stat_res >= 0)
6966 reload = TRUE;
6967 else
6968 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006969 if (stat_res < 0)
6970 reason = "deleted";
6971 else if (bufIsChanged(buf))
6972 reason = "conflict";
6973 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6974 reason = "changed";
6975 else if (orig_mode != buf->b_orig_mode)
6976 reason = "mode";
6977 else
6978 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006979
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006980#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006981 /*
6982 * Only give the warning if there are no FileChangedShell
6983 * autocommands.
6984 * Avoid being called recursively by setting "busy".
6985 */
6986 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006987# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006988 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6989 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006990# endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006991 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006992 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6993 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006994 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006995 busy = FALSE;
6996 if (n)
6997 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006998 if (!bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006999 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00007000# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007001 s = get_vim_var_str(VV_FCS_CHOICE);
7002 if (STRCMP(s, "reload") == 0 && *reason != 'd')
7003 reload = TRUE;
7004 else if (STRCMP(s, "ask") == 0)
7005 n = FALSE;
7006 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00007007# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007008 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007009 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007010 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007011#endif
7012 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007013 if (*reason == 'd')
7014 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00007015 else
7016 {
7017 helpmesg = TRUE;
7018#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7019 can_reload = TRUE;
7020#endif
7021 /*
7022 * Check if the file contents really changed to avoid
7023 * giving a warning when only the timestamp was set (e.g.,
7024 * checked out of CVS). Always warn when the buffer was
7025 * changed.
7026 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007027 if (reason[2] == 'n')
7028 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007029 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007030 mesg2 = _("See \":help W12\" for more info.");
7031 }
7032 else if (reason[1] == 'h')
7033 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007034 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007035 mesg2 = _("See \":help W11\" for more info.");
7036 }
7037 else if (*reason == 'm')
7038 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007039 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007040 mesg2 = _("See \":help W16\" for more info.");
7041 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00007042 else
7043 /* Only timestamp changed, store it to avoid a warning
7044 * in check_mtime() later. */
7045 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007046 }
7047 }
7048 }
7049
7050 }
7051 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
7052 && vim_fexists(buf->b_ffname))
7053 {
7054 retval = 1;
7055 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
7056 buf->b_flags |= BF_NEW_W;
7057#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7058 can_reload = TRUE;
7059#endif
7060 }
7061
7062 if (mesg != NULL)
7063 {
7064 path = home_replace_save(buf, buf->b_fname);
7065 if (path != NULL)
7066 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007067 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007068 mesg2 = "";
7069 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
7070 + STRLEN(mesg2) + 2));
7071 sprintf((char *)tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00007072#ifdef FEAT_EVAL
7073 /* Set warningmsg here, before the unimportant and output-specific
7074 * mesg2 has been appended. */
7075 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
7076#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007077#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7078 if (can_reload)
7079 {
7080 if (*mesg2 != NUL)
7081 {
7082 STRCAT(tbuf, "\n");
7083 STRCAT(tbuf, mesg2);
7084 }
7085 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01007086 (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007087 reload = TRUE;
7088 }
7089 else
7090#endif
7091 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
7092 {
7093 if (*mesg2 != NUL)
7094 {
7095 STRCAT(tbuf, "; ");
7096 STRCAT(tbuf, mesg2);
7097 }
7098 EMSG(tbuf);
7099 retval = 2;
7100 }
7101 else
7102 {
Bram Moolenaared203462004-06-16 11:19:22 +00007103# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00007104 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00007105# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007106 {
7107 msg_start();
Bram Moolenaar8820b482017-03-16 17:23:31 +01007108 msg_puts_attr(tbuf, HL_ATTR(HLF_E) + MSG_HIST);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007109 if (*mesg2 != NUL)
7110 msg_puts_attr((char_u *)mesg2,
Bram Moolenaar8820b482017-03-16 17:23:31 +01007111 HL_ATTR(HLF_W) + MSG_HIST);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007112 msg_clr_eos();
7113 (void)msg_end();
7114 if (emsg_silent == 0)
7115 {
7116 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00007117# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00007118 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00007119# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007120 /* give the user some time to think about it */
7121 ui_delay(1000L, TRUE);
7122
7123 /* don't redraw and erase the message */
7124 redraw_cmdline = FALSE;
7125 }
7126 }
7127 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007128 }
7129
7130 vim_free(path);
7131 vim_free(tbuf);
7132 }
7133 }
7134
7135 if (reload)
Bram Moolenaar465748e2012-08-29 18:50:54 +02007136 {
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007137 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00007138 buf_reload(buf, orig_mode);
Bram Moolenaar465748e2012-08-29 18:50:54 +02007139#ifdef FEAT_PERSISTENT_UNDO
7140 if (buf->b_p_udf && buf->b_ffname != NULL)
7141 {
7142 char_u hash[UNDO_HASH_SIZE];
7143 buf_T *save_curbuf = curbuf;
7144
7145 /* Any existing undo file is unusable, write it now. */
7146 curbuf = buf;
7147 u_compute_hash(hash);
7148 u_write_undo(NULL, FALSE, buf, hash);
7149 curbuf = save_curbuf;
7150 }
7151#endif
7152 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007153
Bram Moolenaar56718732006-03-15 22:53:57 +00007154#ifdef FEAT_AUTOCMD
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00007155 /* Trigger FileChangedShell when the file was changed in any way. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007156 if (bufref_valid(&bufref) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00007157 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
7158 buf->b_fname, buf->b_fname, FALSE, buf);
7159#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007160#ifdef FEAT_GUI
7161 /* restore this in case an autocommand has set it; it would break
7162 * 'mousefocus' */
7163 need_mouse_correct = save_mouse_correct;
7164#endif
7165
7166 return retval;
7167}
7168
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007169/*
7170 * Reload a buffer that is already loaded.
7171 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00007172 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
7173 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007174 */
7175 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007176buf_reload(buf_T *buf, int orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007177{
7178 exarg_T ea;
7179 pos_T old_cursor;
7180 linenr_T old_topline;
7181 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007182 buf_T *savebuf;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007183 bufref_T bufref;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007184 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007185 aco_save_T aco;
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007186 int flags = READ_NEW;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007187
7188 /* set curwin/curbuf for "buf" and save some things */
7189 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007190
7191 /* We only want to read the text from the file, not reset the syntax
7192 * highlighting, clear marks, diff status, etc. Force the fileformat
7193 * and encoding to be the same. */
7194 if (prep_exarg(&ea, buf) == OK)
7195 {
7196 old_cursor = curwin->w_cursor;
7197 old_topline = curwin->w_topline;
7198
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007199 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007200 {
7201 /* Save all the text, so that the reload can be undone.
7202 * Sync first so that this is a separate undo-able action. */
7203 u_sync(FALSE);
7204 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
7205 flags |= READ_KEEP_UNDO;
7206 }
7207
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007208 /*
7209 * To behave like when a new file is edited (matters for
7210 * BufReadPost autocommands) we first need to delete the current
7211 * buffer contents. But if reading the file fails we should keep
7212 * the old contents. Can't use memory only, the file might be
7213 * too big. Use a hidden buffer to move the buffer contents to.
7214 */
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01007215 if (BUFEMPTY() || saved == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007216 savebuf = NULL;
7217 else
7218 {
7219 /* Allocate a buffer without putting it in the buffer list. */
7220 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007221 set_bufref(&bufref, savebuf);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007222 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007223 {
7224 /* Open the memline. */
7225 curbuf = savebuf;
7226 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00007227 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007228 curbuf = buf;
7229 curwin->w_buffer = buf;
7230 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00007231 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007232 || move_lines(buf, savebuf) == FAIL)
7233 {
7234 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
7235 buf->b_fname);
7236 saved = FAIL;
7237 }
7238 }
7239
7240 if (saved == OK)
7241 {
7242 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
7243#ifdef FEAT_AUTOCMD
7244 keep_filetype = TRUE; /* don't detect 'filetype' */
7245#endif
7246 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
7247 (linenr_T)0,
Bram Moolenaare13b9af2017-01-13 22:01:02 +01007248 (linenr_T)MAXLNUM, &ea, flags) != OK)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007249 {
7250#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
7251 if (!aborting())
7252#endif
7253 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007254 if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007255 {
7256 /* Put the text back from the save buffer. First
7257 * delete any lines that readfile() added. */
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01007258 while (!BUFEMPTY())
Bram Moolenaar8424a622006-04-19 21:23:36 +00007259 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007260 break;
7261 (void)move_lines(savebuf, buf);
7262 }
7263 }
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007264 else if (buf == curbuf) /* "buf" still valid */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007265 {
7266 /* Mark the buffer as unmodified and free undo info. */
7267 unchanged(buf, TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007268 if ((flags & READ_KEEP_UNDO) == 0)
7269 {
7270 u_blockfree(buf);
7271 u_clearall(buf);
7272 }
7273 else
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007274 {
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007275 /* Mark all undo states as changed. */
7276 u_unchanged(curbuf);
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007277 }
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007278 }
7279 }
7280 vim_free(ea.cmd);
7281
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02007282 if (savebuf != NULL && bufref_valid(&bufref))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007283 wipe_buffer(savebuf, FALSE);
7284
7285#ifdef FEAT_DIFF
7286 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00007287 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007288#endif
7289
7290 /* Restore the topline and cursor position and check it (lines may
7291 * have been removed). */
7292 if (old_topline > curbuf->b_ml.ml_line_count)
7293 curwin->w_topline = curbuf->b_ml.ml_line_count;
7294 else
7295 curwin->w_topline = old_topline;
7296 curwin->w_cursor = old_cursor;
7297 check_cursor();
7298 update_topline();
7299#ifdef FEAT_AUTOCMD
7300 keep_filetype = FALSE;
7301#endif
7302#ifdef FEAT_FOLDING
7303 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007304 win_T *wp;
7305 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007306
7307 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007308 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007309 if (wp->w_buffer == curwin->w_buffer
7310 && !foldmethodIsManual(wp))
7311 foldUpdateAll(wp);
7312 }
7313#endif
7314 /* If the mode didn't change and 'readonly' was set, keep the old
7315 * value; the user probably used the ":view" command. But don't
7316 * reset it, might have had a read error. */
7317 if (orig_mode == curbuf->b_orig_mode)
7318 curbuf->b_p_ro |= old_ro;
Bram Moolenaar52f85b72013-01-30 14:13:56 +01007319
7320 /* Modelines must override settings done by autocommands. */
7321 do_modelines(0);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007322 }
7323
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007324 /* restore curwin/curbuf and a few other things */
7325 aucmd_restbuf(&aco);
7326 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007327}
7328
Bram Moolenaar071d4272004-06-13 20:20:40 +00007329 void
Bram Moolenaar8767f522016-07-01 17:17:39 +02007330buf_store_time(buf_T *buf, stat_T *st, char_u *fname UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007331{
7332 buf->b_mtime = (long)st->st_mtime;
Bram Moolenaar914703b2010-05-31 21:59:46 +02007333 buf->b_orig_size = st->st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007334#ifdef HAVE_ST_MODE
7335 buf->b_orig_mode = (int)st->st_mode;
7336#else
7337 buf->b_orig_mode = mch_getperm(fname);
7338#endif
7339}
7340
7341/*
7342 * Adjust the line with missing eol, used for the next write.
7343 * Used for do_filter(), when the input lines for the filter are deleted.
7344 */
7345 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007346write_lnum_adjust(linenr_T offset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347{
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01007348 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
7349 curbuf->b_no_eol_lnum += offset;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007350}
7351
Bram Moolenaarda440d22016-01-16 21:27:23 +01007352#if defined(TEMPDIRNAMES) || defined(FEAT_EVAL) || defined(PROTO)
7353/*
7354 * Delete "name" and everything in it, recursively.
7355 * return 0 for succes, -1 if some file was not deleted.
7356 */
7357 int
7358delete_recursive(char_u *name)
7359{
7360 int result = 0;
7361 char_u **files;
7362 int file_count;
7363 int i;
7364 char_u *exp;
7365
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007366 /* A symbolic link to a directory itself is deleted, not the directory it
7367 * points to. */
7368 if (
Bram Moolenaar203258c2016-01-17 22:15:16 +01007369# if defined(UNIX) || defined(WIN32)
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007370 mch_isrealdir(name)
Bram Moolenaar203258c2016-01-17 22:15:16 +01007371# else
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007372 mch_isdir(name)
Bram Moolenaar43a34f92016-01-17 15:56:34 +01007373# endif
7374 )
Bram Moolenaarda440d22016-01-16 21:27:23 +01007375 {
7376 vim_snprintf((char *)NameBuff, MAXPATHL, "%s/*", name);
7377 exp = vim_strsave(NameBuff);
7378 if (exp == NULL)
7379 return -1;
7380 if (gen_expand_wildcards(1, &exp, &file_count, &files,
Bram Moolenaar336bd622016-01-17 18:23:58 +01007381 EW_DIR|EW_FILE|EW_SILENT|EW_ALLLINKS|EW_DODOT|EW_EMPTYOK) == OK)
Bram Moolenaarda440d22016-01-16 21:27:23 +01007382 {
7383 for (i = 0; i < file_count; ++i)
7384 if (delete_recursive(files[i]) != 0)
7385 result = -1;
7386 FreeWild(file_count, files);
7387 }
7388 else
7389 result = -1;
7390 vim_free(exp);
7391 (void)mch_rmdir(name);
7392 }
7393 else
7394 result = mch_remove(name) == 0 ? 0 : -1;
7395
7396 return result;
7397}
7398#endif
7399
Bram Moolenaar071d4272004-06-13 20:20:40 +00007400#if defined(TEMPDIRNAMES) || defined(PROTO)
7401static long temp_count = 0; /* Temp filename counter. */
7402
7403/*
7404 * Delete the temp directory and all files it contains.
7405 */
7406 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007407vim_deltempdir(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007408{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007409 if (vim_tempdir != NULL)
7410 {
Bram Moolenaarda440d22016-01-16 21:27:23 +01007411 /* remove the trailing path separator */
7412 gettail(vim_tempdir)[-1] = NUL;
7413 delete_recursive(vim_tempdir);
Bram Moolenaard23a8232018-02-10 18:45:26 +01007414 VIM_CLEAR(vim_tempdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007415 }
7416}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007417
7418/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007419 * Directory "tempdir" was created. Expand this name to a full path and put
7420 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7421 * "tempdir" must be no longer than MAXPATHL.
7422 */
7423 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007424vim_settempdir(char_u *tempdir)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007425{
7426 char_u *buf;
7427
7428 buf = alloc((unsigned)MAXPATHL + 2);
7429 if (buf != NULL)
7430 {
7431 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7432 STRCPY(buf, tempdir);
Bram Moolenaara06ecab2016-07-16 14:47:36 +02007433 add_pathsep(buf);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007434 vim_tempdir = vim_strsave(buf);
7435 vim_free(buf);
7436 }
7437}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007438#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007439
7440/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007441 * vim_tempname(): Return a unique name that can be used for a temp file.
7442 *
Bram Moolenaar76ae22f2016-06-13 20:00:29 +02007443 * The temp file is NOT guaranteed to be created. If "keep" is FALSE it is
7444 * guaranteed to NOT be created.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007445 *
7446 * The returned pointer is to allocated memory.
7447 * The returned pointer is NULL if no valid name was found.
7448 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007449 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007450vim_tempname(
7451 int extra_char UNUSED, /* char to use in the name instead of '?' */
7452 int keep UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007453{
7454#ifdef USE_TMPNAM
7455 char_u itmp[L_tmpnam]; /* use tmpnam() */
7456#else
7457 char_u itmp[TEMPNAMELEN];
7458#endif
7459
7460#ifdef TEMPDIRNAMES
7461 static char *(tempdirs[]) = {TEMPDIRNAMES};
7462 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007463# ifndef EEXIST
Bram Moolenaar8767f522016-07-01 17:17:39 +02007464 stat_T st;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007465# endif
7466
7467 /*
7468 * This will create a directory for private use by this instance of Vim.
7469 * This is done once, and the same directory is used for all temp files.
7470 * This method avoids security problems because of symlink attacks et al.
7471 * It's also a bit faster, because we only need to check for an existing
7472 * file when creating the directory and not for each temp file.
7473 */
7474 if (vim_tempdir == NULL)
7475 {
7476 /*
7477 * Try the entries in TEMPDIRNAMES to create the temp directory.
7478 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007479 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007480 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007481# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007482 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007483 long nr;
7484 long off;
7485# endif
7486
Bram Moolenaare1a61992015-12-03 21:02:27 +01007487 /* Expand $TMP, leave room for "/v1100000/999999999".
7488 * Skip the directory check if the expansion fails. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007489 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
Bram Moolenaare1a61992015-12-03 21:02:27 +01007490 if (itmp[0] != '$' && mch_isdir(itmp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007491 {
Bram Moolenaare1a61992015-12-03 21:02:27 +01007492 /* directory exists */
Bram Moolenaara06ecab2016-07-16 14:47:36 +02007493 add_pathsep(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007494
Bram Moolenaareaf03392009-11-17 11:08:52 +00007495# ifdef HAVE_MKDTEMP
Bram Moolenaar35d88f42016-06-04 14:52:00 +02007496 {
7497# if defined(UNIX) || defined(VMS)
7498 /* Make sure the umask doesn't remove the executable bit.
7499 * "repl" has been reported to use "177". */
7500 mode_t umask_save = umask(077);
7501# endif
7502 /* Leave room for filename */
7503 STRCAT(itmp, "vXXXXXX");
7504 if (mkdtemp((char *)itmp) != NULL)
7505 vim_settempdir(itmp);
7506# if defined(UNIX) || defined(VMS)
7507 (void)umask(umask_save);
7508# endif
7509 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007510# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007511 /* Get an arbitrary number of up to 6 digits. When it's
7512 * unlikely that it already exists it will be faster,
7513 * otherwise it doesn't matter. The use of mkdir() avoids any
7514 * security problems because of the predictable number. */
7515 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007516 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007517
7518 /* Try up to 10000 different values until we find a name that
7519 * doesn't exist. */
7520 for (off = 0; off < 10000L; ++off)
7521 {
7522 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007523# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007524 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007525# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007526
Bram Moolenaareaf03392009-11-17 11:08:52 +00007527 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7528# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007529 /* If mkdir() does not set errno to EEXIST, check for
7530 * existing file here. There is a race condition then,
7531 * although it's fail-safe. */
7532 if (mch_stat((char *)itmp, &st) >= 0)
7533 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007534# endif
7535# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007536 /* Make sure the umask doesn't remove the executable bit.
7537 * "repl" has been reported to use "177". */
7538 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007539# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007540 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007541# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007542 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007543# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007544 if (r == 0)
7545 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007546 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007547 break;
7548 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007549# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007550 /* If the mkdir() didn't fail because the file/dir exists,
7551 * we probably can't create any dir here, try another
7552 * place. */
7553 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007554# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007555 break;
7556 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007557# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007558 if (vim_tempdir != NULL)
7559 break;
7560 }
7561 }
7562 }
7563
7564 if (vim_tempdir != NULL)
7565 {
7566 /* There is no need to check if the file exists, because we own the
7567 * directory and nobody else creates a file in it. */
7568 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7569 return vim_strsave(itmp);
7570 }
7571
7572 return NULL;
7573
7574#else /* TEMPDIRNAMES */
7575
7576# ifdef WIN3264
7577 char szTempFile[_MAX_PATH + 1];
7578 char buf4[4];
7579 char_u *retval;
7580 char_u *p;
7581
7582 STRCPY(itmp, "");
7583 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
Bram Moolenaarb1891912011-02-09 14:47:03 +01007584 {
7585 szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */
7586 szTempFile[1] = NUL;
7587 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007588 strcpy(buf4, "VIM");
7589 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01007590 if (GetTempFileName(szTempFile, buf4, 0, (LPSTR)itmp) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007591 return NULL;
Bram Moolenaare5c421c2015-03-31 13:33:08 +02007592 if (!keep)
7593 /* GetTempFileName() will create the file, we don't want that */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01007594 (void)DeleteFile((LPSTR)itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007595
7596 /* Backslashes in a temp file name cause problems when filtering with
7597 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7598 * didn't set 'shellslash'. */
7599 retval = vim_strsave(itmp);
7600 if (*p_shcf == '-' || p_ssl)
7601 for (p = retval; *p; ++p)
7602 if (*p == '\\')
7603 *p = '/';
7604 return retval;
7605
7606# else /* WIN3264 */
7607
7608# ifdef USE_TMPNAM
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007609 char_u *p;
7610
Bram Moolenaar071d4272004-06-13 20:20:40 +00007611 /* tmpnam() will make its own name */
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007612 p = tmpnam((char *)itmp);
7613 if (p == NULL || *p == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007614 return NULL;
7615# else
7616 char_u *p;
7617
7618# ifdef VMS_TEMPNAM
7619 /* mktemp() is not working on VMS. It seems to be
7620 * a do-nothing function. Therefore we use tempnam().
7621 */
7622 sprintf((char *)itmp, "VIM%c", extra_char);
7623 p = (char_u *)tempnam("tmp:", (char *)itmp);
7624 if (p != NULL)
7625 {
Bram Moolenaar206f0112014-03-12 16:51:55 +01007626 /* VMS will use '.LIS' if we don't explicitly specify an extension,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007627 * and VIM will then be unable to find the file later */
7628 STRCPY(itmp, p);
7629 STRCAT(itmp, ".txt");
7630 free(p);
7631 }
7632 else
7633 return NULL;
7634# else
7635 STRCPY(itmp, TEMPNAME);
7636 if ((p = vim_strchr(itmp, '?')) != NULL)
7637 *p = extra_char;
7638 if (mktemp((char *)itmp) == NULL)
7639 return NULL;
7640# endif
7641# endif
7642
7643 return vim_strsave(itmp);
7644# endif /* WIN3264 */
7645#endif /* TEMPDIRNAMES */
7646}
7647
7648#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7649/*
Bram Moolenaarb4f6a462015-10-13 19:43:17 +02007650 * Convert all backslashes in fname to forward slashes in-place, unless when
7651 * it looks like a URL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007652 */
7653 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007654forward_slash(char_u *fname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007655{
7656 char_u *p;
7657
Bram Moolenaarb4f6a462015-10-13 19:43:17 +02007658 if (path_with_url(fname))
7659 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007660 for (p = fname; *p != NUL; ++p)
7661# ifdef FEAT_MBYTE
7662 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007663 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007664 ++p;
7665 else
7666# endif
7667 if (*p == '\\')
7668 *p = '/';
7669}
7670#endif
7671
7672
7673/*
7674 * Code for automatic commands.
7675 *
7676 * Only included when "FEAT_AUTOCMD" has been defined.
7677 */
7678
7679#if defined(FEAT_AUTOCMD) || defined(PROTO)
7680
7681/*
7682 * The autocommands are stored in a list for each event.
7683 * Autocommands for the same pattern, that are consecutive, are joined
7684 * together, to avoid having to match the pattern too often.
7685 * The result is an array of Autopat lists, which point to AutoCmd lists:
7686 *
Bram Moolenaar462455e2017-11-10 21:53:11 +01007687 * last_autopat[0] -----------------------------+
7688 * V
Bram Moolenaar071d4272004-06-13 20:20:40 +00007689 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7690 * Autopat.cmds Autopat.cmds
7691 * | |
7692 * V V
7693 * AutoCmd.next AutoCmd.next
7694 * | |
7695 * V V
7696 * AutoCmd.next NULL
7697 * |
7698 * V
7699 * NULL
7700 *
Bram Moolenaar462455e2017-11-10 21:53:11 +01007701 * last_autopat[1] --------+
7702 * V
Bram Moolenaar071d4272004-06-13 20:20:40 +00007703 * first_autopat[1] --> Autopat.next --> NULL
7704 * Autopat.cmds
7705 * |
7706 * V
7707 * AutoCmd.next
7708 * |
7709 * V
7710 * NULL
7711 * etc.
7712 *
7713 * The order of AutoCmds is important, this is the order in which they were
7714 * defined and will have to be executed.
7715 */
7716typedef struct AutoCmd
7717{
7718 char_u *cmd; /* The command to be executed (NULL
7719 when command has been removed) */
7720 char nested; /* If autocommands nest here */
7721 char last; /* last command in list */
7722#ifdef FEAT_EVAL
7723 scid_T scriptID; /* script ID where defined */
7724#endif
7725 struct AutoCmd *next; /* Next AutoCmd in list */
7726} AutoCmd;
7727
7728typedef struct AutoPat
7729{
Bram Moolenaar462455e2017-11-10 21:53:11 +01007730 struct AutoPat *next; /* next AutoPat in AutoPat list; MUST
7731 * be the first entry */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007732 char_u *pat; /* pattern as typed (NULL when pattern
7733 has been removed) */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007734 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007735 AutoCmd *cmds; /* list of commands to do */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007736 int group; /* group ID */
7737 int patlen; /* strlen() of pat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007738 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007739 char allow_dirs; /* Pattern may match whole path */
7740 char last; /* last pattern for apply_autocmds() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007741} AutoPat;
7742
7743static struct event_name
7744{
7745 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007746 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007747} event_names[] =
7748{
7749 {"BufAdd", EVENT_BUFADD},
7750 {"BufCreate", EVENT_BUFADD},
7751 {"BufDelete", EVENT_BUFDELETE},
7752 {"BufEnter", EVENT_BUFENTER},
7753 {"BufFilePost", EVENT_BUFFILEPOST},
7754 {"BufFilePre", EVENT_BUFFILEPRE},
7755 {"BufHidden", EVENT_BUFHIDDEN},
7756 {"BufLeave", EVENT_BUFLEAVE},
7757 {"BufNew", EVENT_BUFNEW},
7758 {"BufNewFile", EVENT_BUFNEWFILE},
7759 {"BufRead", EVENT_BUFREADPOST},
7760 {"BufReadCmd", EVENT_BUFREADCMD},
7761 {"BufReadPost", EVENT_BUFREADPOST},
7762 {"BufReadPre", EVENT_BUFREADPRE},
7763 {"BufUnload", EVENT_BUFUNLOAD},
7764 {"BufWinEnter", EVENT_BUFWINENTER},
7765 {"BufWinLeave", EVENT_BUFWINLEAVE},
7766 {"BufWipeout", EVENT_BUFWIPEOUT},
7767 {"BufWrite", EVENT_BUFWRITEPRE},
7768 {"BufWritePost", EVENT_BUFWRITEPOST},
7769 {"BufWritePre", EVENT_BUFWRITEPRE},
7770 {"BufWriteCmd", EVENT_BUFWRITECMD},
Bram Moolenaar153b7042018-01-31 15:48:32 +01007771 {"CmdlineChanged", EVENT_CMDLINECHANGED},
Bram Moolenaarfafcf0d2017-10-19 18:35:51 +02007772 {"CmdlineEnter", EVENT_CMDLINEENTER},
7773 {"CmdlineLeave", EVENT_CMDLINELEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007774 {"CmdwinEnter", EVENT_CMDWINENTER},
7775 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaard5005162014-08-22 23:05:54 +02007776 {"CmdUndefined", EVENT_CMDUNDEFINED},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007777 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaarcfa3cae2012-07-10 17:14:56 +02007778 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007779 {"CursorHold", EVENT_CURSORHOLD},
7780 {"CursorHoldI", EVENT_CURSORHOLDI},
7781 {"CursorMoved", EVENT_CURSORMOVED},
7782 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaarb7407d32018-02-03 17:36:27 +01007783 {"DirChanged", EVENT_DIRCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007784 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7785 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007786 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7787 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7788 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7789 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007790 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007791 {"FileChangedRO", EVENT_FILECHANGEDRO},
7792 {"FileReadPost", EVENT_FILEREADPOST},
7793 {"FileReadPre", EVENT_FILEREADPRE},
7794 {"FileReadCmd", EVENT_FILEREADCMD},
7795 {"FileType", EVENT_FILETYPE},
7796 {"FileWritePost", EVENT_FILEWRITEPOST},
7797 {"FileWritePre", EVENT_FILEWRITEPRE},
7798 {"FileWriteCmd", EVENT_FILEWRITECMD},
7799 {"FilterReadPost", EVENT_FILTERREADPOST},
7800 {"FilterReadPre", EVENT_FILTERREADPRE},
7801 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7802 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7803 {"FocusGained", EVENT_FOCUSGAINED},
7804 {"FocusLost", EVENT_FOCUSLOST},
7805 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7806 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007807 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007808 {"InsertChange", EVENT_INSERTCHANGE},
7809 {"InsertEnter", EVENT_INSERTENTER},
7810 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaare659c952011-05-19 17:25:41 +02007811 {"InsertCharPre", EVENT_INSERTCHARPRE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007812 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar53744302015-07-17 17:38:22 +02007813 {"OptionSet", EVENT_OPTIONSET},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007814 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7815 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar3b53dfb2012-06-06 18:03:07 +02007816 {"QuitPre", EVENT_QUITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007817 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007818 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007819 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7820 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007821 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007822 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007823 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007824 {"StdinReadPost", EVENT_STDINREADPOST},
7825 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007826 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007827 {"Syntax", EVENT_SYNTAX},
Bram Moolenaarc917da42016-07-19 22:31:36 +02007828 {"TabNew", EVENT_TABNEW},
Bram Moolenaar12c11d52016-07-19 23:13:03 +02007829 {"TabClosed", EVENT_TABCLOSED},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007830 {"TabEnter", EVENT_TABENTER},
7831 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007832 {"TermChanged", EVENT_TERMCHANGED},
7833 {"TermResponse", EVENT_TERMRESPONSE},
Bram Moolenaar186628f2013-03-19 13:33:23 +01007834 {"TextChanged", EVENT_TEXTCHANGED},
7835 {"TextChangedI", EVENT_TEXTCHANGEDI},
Bram Moolenaar5a093432018-02-10 18:15:19 +01007836 {"TextChangedP", EVENT_TEXTCHANGEDP},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007837 {"User", EVENT_USER},
7838 {"VimEnter", EVENT_VIMENTER},
7839 {"VimLeave", EVENT_VIMLEAVE},
7840 {"VimLeavePre", EVENT_VIMLEAVEPRE},
Bram Moolenaarc917da42016-07-19 22:31:36 +02007841 {"WinNew", EVENT_WINNEW},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007842 {"WinEnter", EVENT_WINENTER},
7843 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007844 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007845 {"TextYankPost", EVENT_TEXTYANKPOST},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007846 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007847};
7848
7849static AutoPat *first_autopat[NUM_EVENTS] =
7850{
7851 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7852 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7853 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7854 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007855 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaar53744302015-07-17 17:38:22 +02007856 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007857};
7858
Bram Moolenaar462455e2017-11-10 21:53:11 +01007859static AutoPat *last_autopat[NUM_EVENTS] =
7860{
7861 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7862 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7863 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7864 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7865 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7866 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
7867};
7868
Bram Moolenaar071d4272004-06-13 20:20:40 +00007869/*
7870 * struct used to keep status while executing autocommands for an event.
7871 */
7872typedef struct AutoPatCmd
7873{
7874 AutoPat *curpat; /* next AutoPat to examine */
7875 AutoCmd *nextcmd; /* next AutoCmd to execute */
7876 int group; /* group being used */
7877 char_u *fname; /* fname to match with */
7878 char_u *sfname; /* sfname to match with */
7879 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007880 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007881 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7882 buf is deleted */
7883 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007884} AutoPatCmd;
7885
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007886static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007887
Bram Moolenaar071d4272004-06-13 20:20:40 +00007888/*
7889 * augroups stores a list of autocmd group names.
7890 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007891static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007892#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
Bram Moolenaarb62cc362016-09-03 16:43:53 +02007893/* use get_deleted_augroup() to get this */
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02007894static char_u *deleted_augroup = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007895
7896/*
7897 * The ID of the current group. Group 0 is the default one.
7898 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007899static int current_augroup = AUGROUP_DEFAULT;
7900
7901static int au_need_clean = FALSE; /* need to delete marked patterns */
7902
Bram Moolenaard25c16e2016-01-29 22:13:30 +01007903static void show_autocmd(AutoPat *ap, event_T event);
7904static void au_remove_pat(AutoPat *ap);
7905static void au_remove_cmds(AutoPat *ap);
7906static void au_cleanup(void);
7907static int au_new_group(char_u *name);
7908static void au_del_group(char_u *name);
7909static event_T event_name2nr(char_u *start, char_u **end);
7910static char_u *event_nr2name(event_T event);
7911static char_u *find_end_event(char_u *arg, int have_group);
7912static int event_ignored(event_T event);
7913static int au_get_grouparg(char_u **argp);
7914static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group);
7915static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
7916static void auto_next_pat(AutoPatCmd *apc, int stop_at_last);
Bram Moolenaardffa5b82014-11-19 16:38:07 +01007917#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN)
Bram Moolenaard25c16e2016-01-29 22:13:30 +01007918static int match_file_pat(char_u *pattern, regprog_T **prog, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs);
Bram Moolenaardffa5b82014-11-19 16:38:07 +01007919#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007920
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007921
Bram Moolenaar754b5602006-02-09 23:53:20 +00007922static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007923static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007924static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007925
Bram Moolenaarb62cc362016-09-03 16:43:53 +02007926 static char_u *
7927get_deleted_augroup(void)
7928{
7929 if (deleted_augroup == NULL)
7930 deleted_augroup = (char_u *)_("--Deleted--");
7931 return deleted_augroup;
7932}
7933
Bram Moolenaar071d4272004-06-13 20:20:40 +00007934/*
7935 * Show the autocommands for one AutoPat.
7936 */
7937 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01007938show_autocmd(AutoPat *ap, event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007939{
7940 AutoCmd *ac;
7941
7942 /* Check for "got_int" (here and at various places below), which is set
7943 * when "q" has been hit for the "--more--" prompt */
7944 if (got_int)
7945 return;
7946 if (ap->pat == NULL) /* pattern has been removed */
7947 return;
7948
7949 msg_putchar('\n');
7950 if (got_int)
7951 return;
7952 if (event != last_event || ap->group != last_group)
7953 {
7954 if (ap->group != AUGROUP_DEFAULT)
7955 {
7956 if (AUGROUP_NAME(ap->group) == NULL)
Bram Moolenaar8820b482017-03-16 17:23:31 +01007957 msg_puts_attr(get_deleted_augroup(), HL_ATTR(HLF_E));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007958 else
Bram Moolenaar8820b482017-03-16 17:23:31 +01007959 msg_puts_attr(AUGROUP_NAME(ap->group), HL_ATTR(HLF_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007960 msg_puts((char_u *)" ");
7961 }
Bram Moolenaar8820b482017-03-16 17:23:31 +01007962 msg_puts_attr(event_nr2name(event), HL_ATTR(HLF_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007963 last_event = event;
7964 last_group = ap->group;
7965 msg_putchar('\n');
7966 if (got_int)
7967 return;
7968 }
7969 msg_col = 4;
7970 msg_outtrans(ap->pat);
7971
7972 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7973 {
7974 if (ac->cmd != NULL) /* skip removed commands */
7975 {
7976 if (msg_col >= 14)
7977 msg_putchar('\n');
7978 msg_col = 14;
7979 if (got_int)
7980 return;
7981 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007982#ifdef FEAT_EVAL
7983 if (p_verbose > 0)
7984 last_set_msg(ac->scriptID);
7985#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007986 if (got_int)
7987 return;
7988 if (ac->next != NULL)
7989 {
7990 msg_putchar('\n');
7991 if (got_int)
7992 return;
7993 }
7994 }
7995 }
7996}
7997
7998/*
7999 * Mark an autocommand pattern for deletion.
8000 */
8001 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008002au_remove_pat(AutoPat *ap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008003{
Bram Moolenaard23a8232018-02-10 18:45:26 +01008004 VIM_CLEAR(ap->pat);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008005 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008006 au_need_clean = TRUE;
8007}
8008
8009/*
8010 * Mark all commands for a pattern for deletion.
8011 */
8012 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008013au_remove_cmds(AutoPat *ap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008014{
8015 AutoCmd *ac;
8016
8017 for (ac = ap->cmds; ac != NULL; ac = ac->next)
Bram Moolenaard23a8232018-02-10 18:45:26 +01008018 VIM_CLEAR(ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008019 au_need_clean = TRUE;
8020}
8021
8022/*
8023 * Cleanup autocommands and patterns that have been deleted.
8024 * This is only done when not executing autocommands.
8025 */
8026 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008027au_cleanup(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008028{
8029 AutoPat *ap, **prev_ap;
8030 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008031 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008032
8033 if (autocmd_busy || !au_need_clean)
8034 return;
8035
8036 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008037 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8038 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008039 {
8040 /* loop over all autocommand patterns */
8041 prev_ap = &(first_autopat[(int)event]);
8042 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
8043 {
8044 /* loop over all commands for this pattern */
8045 prev_ac = &(ap->cmds);
8046 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
8047 {
8048 /* remove the command if the pattern is to be deleted or when
8049 * the command has been marked for deletion */
8050 if (ap->pat == NULL || ac->cmd == NULL)
8051 {
8052 *prev_ac = ac->next;
8053 vim_free(ac->cmd);
8054 vim_free(ac);
8055 }
8056 else
8057 prev_ac = &(ac->next);
8058 }
8059
8060 /* remove the pattern if it has been marked for deletion */
8061 if (ap->pat == NULL)
8062 {
Bram Moolenaar462455e2017-11-10 21:53:11 +01008063 if (ap->next == NULL)
8064 {
8065 if (prev_ap == &(first_autopat[(int)event]))
8066 last_autopat[(int)event] = NULL;
8067 else
8068 /* this depends on the "next" field being the first in
8069 * the struct */
8070 last_autopat[(int)event] = (AutoPat *)prev_ap;
8071 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008072 *prev_ap = ap->next;
Bram Moolenaar473de612013-06-08 18:19:48 +02008073 vim_regfree(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008074 vim_free(ap);
8075 }
8076 else
8077 prev_ap = &(ap->next);
8078 }
8079 }
8080
8081 au_need_clean = FALSE;
8082}
8083
8084/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008085 * Called when buffer is freed, to remove/invalidate related buffer-local
8086 * autocmds.
8087 */
8088 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008089aubuflocal_remove(buf_T *buf)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008090{
8091 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008092 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008093 AutoPatCmd *apc;
8094
8095 /* invalidate currently executing autocommands */
8096 for (apc = active_apc_list; apc; apc = apc->next)
8097 if (buf->b_fnum == apc->arg_bufnr)
8098 apc->arg_bufnr = 0;
8099
8100 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008101 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8102 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008103 /* loop over all autocommand patterns */
8104 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8105 if (ap->buflocal_nr == buf->b_fnum)
8106 {
8107 au_remove_pat(ap);
8108 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008109 {
8110 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008111 smsg((char_u *)
8112 _("auto-removing autocommand: %s <buffer=%d>"),
8113 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008114 verbose_leave();
8115 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008116 }
8117 au_cleanup();
8118}
8119
8120/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008121 * Add an autocmd group name.
8122 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8123 */
8124 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008125au_new_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008126{
8127 int i;
8128
8129 i = au_find_group(name);
8130 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
8131 {
8132 /* First try using a free entry. */
8133 for (i = 0; i < augroups.ga_len; ++i)
8134 if (AUGROUP_NAME(i) == NULL)
8135 break;
8136 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
8137 return AUGROUP_ERROR;
8138
8139 AUGROUP_NAME(i) = vim_strsave(name);
8140 if (AUGROUP_NAME(i) == NULL)
8141 return AUGROUP_ERROR;
8142 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008143 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008144 }
8145
8146 return i;
8147}
8148
8149 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008150au_del_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008151{
8152 int i;
8153
8154 i = au_find_group(name);
8155 if (i == AUGROUP_ERROR) /* the group doesn't exist */
8156 EMSG2(_("E367: No such group: \"%s\""), name);
Bram Moolenaarde653f02016-09-03 16:59:06 +02008157 else if (i == current_augroup)
8158 EMSG(_("E936: Cannot delete the current group"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008159 else
8160 {
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008161 event_T event;
8162 AutoPat *ap;
8163 int in_use = FALSE;
8164
8165 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8166 event = (event_T)((int)event + 1))
8167 {
8168 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
Bram Moolenaar5c809082016-09-01 16:21:48 +02008169 if (ap->group == i && ap->pat != NULL)
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008170 {
8171 give_warning((char_u *)_("W19: Deleting augroup that is still in use"), TRUE);
8172 in_use = TRUE;
8173 event = NUM_EVENTS;
8174 break;
8175 }
8176 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008177 vim_free(AUGROUP_NAME(i));
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008178 if (in_use)
8179 {
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008180 AUGROUP_NAME(i) = get_deleted_augroup();
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008181 }
8182 else
8183 AUGROUP_NAME(i) = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008184 }
8185}
8186
8187/*
8188 * Find the ID of an autocmd group name.
8189 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8190 */
8191 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008192au_find_group(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008193{
8194 int i;
8195
8196 for (i = 0; i < augroups.ga_len; ++i)
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008197 if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008198 && STRCMP(AUGROUP_NAME(i), name) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008199 return i;
8200 return AUGROUP_ERROR;
8201}
8202
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008203/*
8204 * Return TRUE if augroup "name" exists.
8205 */
8206 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008207au_has_group(char_u *name)
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008208{
8209 return au_find_group(name) != AUGROUP_ERROR;
8210}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008211
Bram Moolenaar071d4272004-06-13 20:20:40 +00008212/*
8213 * ":augroup {name}".
8214 */
8215 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008216do_augroup(char_u *arg, int del_group)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008217{
8218 int i;
8219
8220 if (del_group)
8221 {
8222 if (*arg == NUL)
8223 EMSG(_(e_argreq));
8224 else
8225 au_del_group(arg);
8226 }
8227 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
8228 current_augroup = AUGROUP_DEFAULT;
8229 else if (*arg) /* ":aug xxx": switch to group xxx */
8230 {
8231 i = au_new_group(arg);
8232 if (i != AUGROUP_ERROR)
8233 current_augroup = i;
8234 }
8235 else /* ":aug": list the group names */
8236 {
8237 msg_start();
8238 for (i = 0; i < augroups.ga_len; ++i)
8239 {
8240 if (AUGROUP_NAME(i) != NULL)
8241 {
8242 msg_puts(AUGROUP_NAME(i));
8243 msg_puts((char_u *)" ");
8244 }
8245 }
8246 msg_clr_eos();
8247 msg_end();
8248 }
8249}
8250
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008251#if defined(EXITFREE) || defined(PROTO)
8252 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008253free_all_autocmds(void)
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008254{
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008255 int i;
8256 char_u *s;
8257
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008258 for (current_augroup = -1; current_augroup < augroups.ga_len;
8259 ++current_augroup)
8260 do_autocmd((char_u *)"", TRUE);
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008261
8262 for (i = 0; i < augroups.ga_len; ++i)
8263 {
8264 s = ((char_u **)(augroups.ga_data))[i];
Bram Moolenaarb62cc362016-09-03 16:43:53 +02008265 if (s != get_deleted_augroup())
Bram Moolenaarf2c4c392016-07-29 20:50:24 +02008266 vim_free(s);
8267 }
8268 ga_clear(&augroups);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008269}
8270#endif
8271
Bram Moolenaar071d4272004-06-13 20:20:40 +00008272/*
8273 * Return the event number for event name "start".
8274 * Return NUM_EVENTS if the event name was not found.
8275 * Return a pointer to the next event name in "end".
8276 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008277 static event_T
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008278event_name2nr(char_u *start, char_u **end)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008279{
8280 char_u *p;
8281 int i;
8282 int len;
8283
Bram Moolenaare99e8442016-07-26 20:43:40 +02008284 /* the event name ends with end of line, '|', a blank or a comma */
Bram Moolenaar1c465442017-03-12 20:10:05 +01008285 for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008286 ;
8287 for (i = 0; event_names[i].name != NULL; ++i)
8288 {
8289 len = (int)STRLEN(event_names[i].name);
8290 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
8291 break;
8292 }
8293 if (*p == ',')
8294 ++p;
8295 *end = p;
8296 if (event_names[i].name == NULL)
8297 return NUM_EVENTS;
8298 return event_names[i].event;
8299}
8300
8301/*
8302 * Return the name for event "event".
8303 */
8304 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008305event_nr2name(event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008306{
8307 int i;
8308
8309 for (i = 0; event_names[i].name != NULL; ++i)
8310 if (event_names[i].event == event)
8311 return (char_u *)event_names[i].name;
8312 return (char_u *)"Unknown";
8313}
8314
8315/*
8316 * Scan over the events. "*" stands for all events.
8317 */
8318 static char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008319find_end_event(
8320 char_u *arg,
8321 int have_group) /* TRUE when group name was found */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008322{
8323 char_u *pat;
8324 char_u *p;
8325
8326 if (*arg == '*')
8327 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008328 if (arg[1] && !VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008329 {
8330 EMSG2(_("E215: Illegal character after *: %s"), arg);
8331 return NULL;
8332 }
8333 pat = arg + 1;
8334 }
8335 else
8336 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008337 for (pat = arg; *pat && *pat != '|' && !VIM_ISWHITE(*pat); pat = p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008338 {
8339 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
8340 {
8341 if (have_group)
8342 EMSG2(_("E216: No such event: %s"), pat);
8343 else
8344 EMSG2(_("E216: No such group or event: %s"), pat);
8345 return NULL;
8346 }
8347 }
8348 }
8349 return pat;
8350}
8351
8352/*
8353 * Return TRUE if "event" is included in 'eventignore'.
8354 */
8355 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008356event_ignored(event_T event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008357{
8358 char_u *p = p_ei;
8359
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008360 while (*p != NUL)
8361 {
8362 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8363 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008364 if (event_name2nr(p, &p) == event)
8365 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008366 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008367
8368 return FALSE;
8369}
8370
8371/*
8372 * Return OK when the contents of p_ei is valid, FAIL otherwise.
8373 */
8374 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008375check_ei(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008376{
8377 char_u *p = p_ei;
8378
Bram Moolenaar071d4272004-06-13 20:20:40 +00008379 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008380 {
8381 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8382 {
8383 p += 3;
8384 if (*p == ',')
8385 ++p;
8386 }
8387 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008388 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008389 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008390
8391 return OK;
8392}
8393
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008394# if defined(FEAT_SYN_HL) || defined(PROTO)
8395
8396/*
8397 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
8398 * buffer loaded into the window. "what" must start with a comma.
8399 * Returns the old value of 'eventignore' in allocated memory.
8400 */
8401 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008402au_event_disable(char *what)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008403{
8404 char_u *new_ei;
8405 char_u *save_ei;
8406
8407 save_ei = vim_strsave(p_ei);
8408 if (save_ei != NULL)
8409 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008410 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008411 if (new_ei != NULL)
8412 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008413 if (*what == ',' && *p_ei == NUL)
8414 STRCPY(new_ei, what + 1);
8415 else
8416 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008417 set_string_option_direct((char_u *)"ei", -1, new_ei,
8418 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008419 vim_free(new_ei);
8420 }
8421 }
8422 return save_ei;
8423}
8424
8425 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008426au_event_restore(char_u *old_ei)
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008427{
8428 if (old_ei != NULL)
8429 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008430 set_string_option_direct((char_u *)"ei", -1, old_ei,
8431 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008432 vim_free(old_ei);
8433 }
8434}
8435# endif /* FEAT_SYN_HL */
8436
Bram Moolenaar071d4272004-06-13 20:20:40 +00008437/*
8438 * do_autocmd() -- implements the :autocmd command. Can be used in the
8439 * following ways:
8440 *
8441 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8442 * will be automatically executed for <event>
8443 * when editing a file matching <pat>, in
8444 * the current group.
8445 * :autocmd <event> <pat> Show the auto-commands associated with
8446 * <event> and <pat>.
8447 * :autocmd <event> Show the auto-commands associated with
8448 * <event>.
8449 * :autocmd Show all auto-commands.
8450 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
8451 * <event> and <pat>, and add the command
8452 * <cmd>, for the current group.
8453 * :autocmd! <event> <pat> Remove all auto-commands associated with
8454 * <event> and <pat> for the current group.
8455 * :autocmd! <event> Remove all auto-commands associated with
8456 * <event> for the current group.
8457 * :autocmd! Remove ALL auto-commands for the current
8458 * group.
8459 *
8460 * Multiple events and patterns may be given separated by commas. Here are
8461 * some examples:
8462 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8463 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8464 *
8465 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008466 *
8467 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008468 */
8469 void
Bram Moolenaare99e8442016-07-26 20:43:40 +02008470do_autocmd(char_u *arg_in, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008471{
Bram Moolenaare99e8442016-07-26 20:43:40 +02008472 char_u *arg = arg_in;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008473 char_u *pat;
8474 char_u *envpat = NULL;
8475 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008476 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008477 int need_free = FALSE;
8478 int nested = FALSE;
8479 int group;
8480
Bram Moolenaare99e8442016-07-26 20:43:40 +02008481 if (*arg == '|')
8482 {
8483 arg = (char_u *)"";
8484 group = AUGROUP_ALL; /* no argument, use all groups */
8485 }
8486 else
8487 {
8488 /*
8489 * Check for a legal group name. If not, use AUGROUP_ALL.
8490 */
8491 group = au_get_grouparg(&arg);
8492 if (arg == NULL) /* out of memory */
8493 return;
8494 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008495
8496 /*
8497 * Scan over the events.
8498 * If we find an illegal name, return here, don't do anything.
8499 */
8500 pat = find_end_event(arg, group != AUGROUP_ALL);
8501 if (pat == NULL)
8502 return;
8503
Bram Moolenaar071d4272004-06-13 20:20:40 +00008504 pat = skipwhite(pat);
Bram Moolenaare99e8442016-07-26 20:43:40 +02008505 if (*pat == '|')
Bram Moolenaar071d4272004-06-13 20:20:40 +00008506 {
Bram Moolenaare99e8442016-07-26 20:43:40 +02008507 pat = (char_u *)"";
8508 cmd = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +00008509 }
Bram Moolenaare99e8442016-07-26 20:43:40 +02008510 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008511 {
Bram Moolenaare99e8442016-07-26 20:43:40 +02008512 /*
8513 * Scan over the pattern. Put a NUL at the end.
8514 */
8515 cmd = pat;
Bram Moolenaar1c465442017-03-12 20:10:05 +01008516 while (*cmd && (!VIM_ISWHITE(*cmd) || cmd[-1] == '\\'))
Bram Moolenaare99e8442016-07-26 20:43:40 +02008517 cmd++;
8518 if (*cmd)
8519 *cmd++ = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008520
Bram Moolenaare99e8442016-07-26 20:43:40 +02008521 /* Expand environment variables in the pattern. Set 'shellslash', we want
8522 * forward slashes here. */
8523 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8524 {
8525#ifdef BACKSLASH_IN_FILENAME
8526 int p_ssl_save = p_ssl;
8527
8528 p_ssl = TRUE;
8529#endif
8530 envpat = expand_env_save(pat);
8531#ifdef BACKSLASH_IN_FILENAME
8532 p_ssl = p_ssl_save;
8533#endif
8534 if (envpat != NULL)
8535 pat = envpat;
8536 }
8537
8538 /*
8539 * Check for "nested" flag.
8540 */
8541 cmd = skipwhite(cmd);
Bram Moolenaar1c465442017-03-12 20:10:05 +01008542 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && VIM_ISWHITE(cmd[6]))
Bram Moolenaare99e8442016-07-26 20:43:40 +02008543 {
8544 nested = TRUE;
8545 cmd = skipwhite(cmd + 6);
8546 }
8547
8548 /*
8549 * Find the start of the commands.
8550 * Expand <sfile> in it.
8551 */
8552 if (*cmd != NUL)
8553 {
8554 cmd = expand_sfile(cmd);
8555 if (cmd == NULL) /* some error */
8556 return;
8557 need_free = TRUE;
8558 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008559 }
8560
8561 /*
8562 * Print header when showing autocommands.
8563 */
8564 if (!forceit && *cmd == NUL)
8565 {
8566 /* Highlight title */
8567 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
8568 }
8569
8570 /*
8571 * Loop over the events.
8572 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008573 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008574 last_group = AUGROUP_ERROR; /* for listing the group name */
Bram Moolenaare99e8442016-07-26 20:43:40 +02008575 if (*arg == '*' || *arg == NUL || *arg == '|')
Bram Moolenaar071d4272004-06-13 20:20:40 +00008576 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008577 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8578 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008579 if (do_autocmd_event(event, pat,
8580 nested, cmd, forceit, group) == FAIL)
8581 break;
8582 }
8583 else
8584 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01008585 while (*arg && *arg != '|' && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008586 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8587 nested, cmd, forceit, group) == FAIL)
8588 break;
8589 }
8590
8591 if (need_free)
8592 vim_free(cmd);
8593 vim_free(envpat);
8594}
8595
8596/*
8597 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8598 * The "argp" argument is advanced to the following argument.
8599 *
8600 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8601 */
8602 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008603au_get_grouparg(char_u **argp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008604{
8605 char_u *group_name;
8606 char_u *p;
8607 char_u *arg = *argp;
8608 int group = AUGROUP_ALL;
8609
Bram Moolenaar1c465442017-03-12 20:10:05 +01008610 for (p = arg; *p && !VIM_ISWHITE(*p) && *p != '|'; ++p)
Bram Moolenaare99e8442016-07-26 20:43:40 +02008611 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008612 if (p > arg)
8613 {
8614 group_name = vim_strnsave(arg, (int)(p - arg));
8615 if (group_name == NULL) /* out of memory */
8616 return AUGROUP_ERROR;
8617 group = au_find_group(group_name);
8618 if (group == AUGROUP_ERROR)
8619 group = AUGROUP_ALL; /* no match, use all groups */
8620 else
8621 *argp = skipwhite(p); /* match, skip over group name */
8622 vim_free(group_name);
8623 }
8624 return group;
8625}
8626
8627/*
8628 * do_autocmd() for one event.
8629 * If *pat == NUL do for all patterns.
8630 * If *cmd == NUL show entries.
8631 * If forceit == TRUE delete entries.
8632 * If group is not AUGROUP_ALL, only use this group.
8633 */
8634 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008635do_autocmd_event(
8636 event_T event,
8637 char_u *pat,
8638 int nested,
8639 char_u *cmd,
8640 int forceit,
8641 int group)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008642{
8643 AutoPat *ap;
8644 AutoPat **prev_ap;
8645 AutoCmd *ac;
8646 AutoCmd **prev_ac;
8647 int brace_level;
8648 char_u *endpat;
8649 int findgroup;
8650 int allgroups;
8651 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008652 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008653 int buflocal_nr;
8654 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008655
8656 if (group == AUGROUP_ALL)
8657 findgroup = current_augroup;
8658 else
8659 findgroup = group;
8660 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8661
8662 /*
8663 * Show or delete all patterns for an event.
8664 */
8665 if (*pat == NUL)
8666 {
8667 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8668 {
8669 if (forceit) /* delete the AutoPat, if it's in the current group */
8670 {
8671 if (ap->group == findgroup)
8672 au_remove_pat(ap);
8673 }
8674 else if (group == AUGROUP_ALL || ap->group == group)
8675 show_autocmd(ap, event);
8676 }
8677 }
8678
8679 /*
8680 * Loop through all the specified patterns.
8681 */
8682 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8683 {
8684 /*
8685 * Find end of the pattern.
8686 * Watch out for a comma in braces, like "*.\{obj,o\}".
8687 */
8688 brace_level = 0;
8689 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
Bram Moolenaar6b9be1b2015-07-28 13:33:45 +02008690 || (endpat > pat && endpat[-1] == '\\')); ++endpat)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008691 {
8692 if (*endpat == '{')
8693 brace_level++;
8694 else if (*endpat == '}')
8695 brace_level--;
8696 }
8697 if (pat == endpat) /* ignore single comma */
8698 continue;
8699 patlen = (int)(endpat - pat);
8700
8701 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008702 * detect special <buflocal[=X]> buffer-local patterns
8703 */
8704 is_buflocal = FALSE;
8705 buflocal_nr = 0;
8706
Bram Moolenaar1e997822015-02-17 16:04:57 +01008707 if (patlen >= 8 && STRNCMP(pat, "<buffer", 7) == 0
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008708 && pat[patlen - 1] == '>')
8709 {
Bram Moolenaar1e997822015-02-17 16:04:57 +01008710 /* "<buffer...>": Error will be printed only for addition.
8711 * printing and removing will proceed silently. */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008712 is_buflocal = TRUE;
8713 if (patlen == 8)
Bram Moolenaar1e997822015-02-17 16:04:57 +01008714 /* "<buffer>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008715 buflocal_nr = curbuf->b_fnum;
8716 else if (patlen > 9 && pat[7] == '=')
8717 {
Bram Moolenaar1e997822015-02-17 16:04:57 +01008718 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0)
8719 /* "<buffer=abuf>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008720 buflocal_nr = autocmd_bufnr;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008721 else if (skipdigits(pat + 8) == pat + patlen - 1)
Bram Moolenaar1e997822015-02-17 16:04:57 +01008722 /* "<buffer=123>" */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008723 buflocal_nr = atoi((char *)pat + 8);
8724 }
8725 }
8726
8727 if (is_buflocal)
8728 {
8729 /* normalize pat into standard "<buffer>#N" form */
8730 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8731 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008732 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008733 }
8734
8735 /*
Bram Moolenaar462455e2017-11-10 21:53:11 +01008736 * Find AutoPat entries with this pattern. When adding a command it
8737 * always goes at or after the last one, so start at the end.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008738 */
Bram Moolenaar462455e2017-11-10 21:53:11 +01008739 if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL)
8740 prev_ap = &last_autopat[(int)event];
8741 else
8742 prev_ap = &first_autopat[(int)event];
Bram Moolenaar071d4272004-06-13 20:20:40 +00008743 while ((ap = *prev_ap) != NULL)
8744 {
8745 if (ap->pat != NULL)
8746 {
8747 /* Accept a pattern when:
8748 * - a group was specified and it's that group, or a group was
8749 * not specified and it's the current group, or a group was
8750 * not specified and we are listing
8751 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008752 * - the pattern matches.
8753 * For <buffer[=X]>, this condition works because we normalize
8754 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008755 */
8756 if ((allgroups || ap->group == findgroup)
8757 && ap->patlen == patlen
8758 && STRNCMP(pat, ap->pat, patlen) == 0)
8759 {
8760 /*
8761 * Remove existing autocommands.
8762 * If adding any new autocmd's for this AutoPat, don't
8763 * delete the pattern from the autopat list, append to
8764 * this list.
8765 */
8766 if (forceit)
8767 {
8768 if (*cmd != NUL && ap->next == NULL)
8769 {
8770 au_remove_cmds(ap);
8771 break;
8772 }
8773 au_remove_pat(ap);
8774 }
8775
8776 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008777 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008778 */
8779 else if (*cmd == NUL)
8780 show_autocmd(ap, event);
8781
8782 /*
8783 * Add autocmd to this autopat, if it's the last one.
8784 */
8785 else if (ap->next == NULL)
8786 break;
8787 }
8788 }
8789 prev_ap = &ap->next;
8790 }
8791
8792 /*
8793 * Add a new command.
8794 */
8795 if (*cmd != NUL)
8796 {
8797 /*
8798 * If the pattern we want to add a command to does appear at the
8799 * end of the list (or not is not in the list at all), add the
8800 * pattern at the end of the list.
8801 */
8802 if (ap == NULL)
8803 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008804 /* refuse to add buffer-local ap if buffer number is invalid */
8805 if (is_buflocal && (buflocal_nr == 0
8806 || buflist_findnr(buflocal_nr) == NULL))
8807 {
8808 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
8809 buflocal_nr);
8810 return FAIL;
8811 }
8812
Bram Moolenaar071d4272004-06-13 20:20:40 +00008813 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8814 if (ap == NULL)
8815 return FAIL;
8816 ap->pat = vim_strnsave(pat, patlen);
8817 ap->patlen = patlen;
8818 if (ap->pat == NULL)
8819 {
8820 vim_free(ap);
8821 return FAIL;
8822 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008823
8824 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008825 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008826 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008827 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008828 }
8829 else
8830 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008831 char_u *reg_pat;
8832
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008833 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008834 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008835 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008836 if (reg_pat != NULL)
8837 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008838 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008839 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008840 {
8841 vim_free(ap->pat);
8842 vim_free(ap);
8843 return FAIL;
8844 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008845 }
8846 ap->cmds = NULL;
8847 *prev_ap = ap;
Bram Moolenaar462455e2017-11-10 21:53:11 +01008848 last_autopat[(int)event] = ap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008849 ap->next = NULL;
8850 if (group == AUGROUP_ALL)
8851 ap->group = current_augroup;
8852 else
8853 ap->group = group;
8854 }
8855
8856 /*
8857 * Add the autocmd at the end of the AutoCmd list.
8858 */
8859 prev_ac = &(ap->cmds);
8860 while ((ac = *prev_ac) != NULL)
8861 prev_ac = &ac->next;
8862 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8863 if (ac == NULL)
8864 return FAIL;
8865 ac->cmd = vim_strsave(cmd);
8866#ifdef FEAT_EVAL
8867 ac->scriptID = current_SID;
8868#endif
8869 if (ac->cmd == NULL)
8870 {
8871 vim_free(ac);
8872 return FAIL;
8873 }
8874 ac->next = NULL;
8875 *prev_ac = ac;
8876 ac->nested = nested;
8877 }
8878 }
8879
8880 au_cleanup(); /* may really delete removed patterns/commands now */
8881 return OK;
8882}
8883
8884/*
8885 * Implementation of ":doautocmd [group] event [fname]".
8886 * Return OK for success, FAIL for failure;
8887 */
8888 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008889do_doautocmd(
8890 char_u *arg,
Bram Moolenaar1610d052016-06-09 22:53:01 +02008891 int do_msg, /* give message for no matching autocmds? */
8892 int *did_something)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008893{
8894 char_u *fname;
8895 int nothing_done = TRUE;
8896 int group;
8897
Bram Moolenaar1610d052016-06-09 22:53:01 +02008898 if (did_something != NULL)
Bram Moolenaar76ae22f2016-06-13 20:00:29 +02008899 *did_something = FALSE;
Bram Moolenaar1610d052016-06-09 22:53:01 +02008900
Bram Moolenaar071d4272004-06-13 20:20:40 +00008901 /*
8902 * Check for a legal group name. If not, use AUGROUP_ALL.
8903 */
8904 group = au_get_grouparg(&arg);
8905 if (arg == NULL) /* out of memory */
8906 return FAIL;
8907
8908 if (*arg == '*')
8909 {
8910 EMSG(_("E217: Can't execute autocommands for ALL events"));
8911 return FAIL;
8912 }
8913
8914 /*
8915 * Scan over the events.
8916 * If we find an illegal name, return here, don't do anything.
8917 */
8918 fname = find_end_event(arg, group != AUGROUP_ALL);
8919 if (fname == NULL)
8920 return FAIL;
8921
8922 fname = skipwhite(fname);
8923
8924 /*
8925 * Loop over the events.
8926 */
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02008927 while (*arg && !ends_excmd(*arg) && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008928 if (apply_autocmds_group(event_name2nr(arg, &arg),
8929 fname, NULL, TRUE, group, curbuf, NULL))
8930 nothing_done = FALSE;
8931
8932 if (nothing_done && do_msg)
8933 MSG(_("No matching autocommands"));
Bram Moolenaar1610d052016-06-09 22:53:01 +02008934 if (did_something != NULL)
8935 *did_something = !nothing_done;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008936
8937#ifdef FEAT_EVAL
8938 return aborting() ? FAIL : OK;
8939#else
8940 return OK;
8941#endif
8942}
8943
8944/*
8945 * ":doautoall": execute autocommands for each loaded buffer.
8946 */
8947 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01008948ex_doautoall(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008949{
8950 int retval;
8951 aco_save_T aco;
8952 buf_T *buf;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008953 bufref_T bufref;
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008954 char_u *arg = eap->arg;
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008955 int call_do_modelines = check_nomodeline(&arg);
Bram Moolenaar1610d052016-06-09 22:53:01 +02008956 int did_aucmd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957
8958 /*
8959 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8960 * equal to curbuf, but for some buffers there may not be a window.
8961 * So we change the buffer for the current window for a moment. This
8962 * gives problems when the autocommands make changes to the list of
8963 * buffers or windows...
8964 */
Bram Moolenaar29323592016-07-24 22:04:11 +02008965 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008966 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008967 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008968 {
8969 /* find a window for this buffer and save some values */
8970 aucmd_prepbuf(&aco, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008971 set_bufref(&bufref, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008972
8973 /* execute the autocommands for this buffer */
Bram Moolenaar1610d052016-06-09 22:53:01 +02008974 retval = do_doautocmd(arg, FALSE, &did_aucmd);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008975
Bram Moolenaar1610d052016-06-09 22:53:01 +02008976 if (call_do_modelines && did_aucmd)
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008977 {
8978 /* Execute the modeline settings, but don't set window-local
8979 * options if we are using the current window for another
8980 * buffer. */
8981 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
8982 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008983
8984 /* restore the current window */
8985 aucmd_restbuf(&aco);
8986
8987 /* stop if there is some error or buffer was deleted */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02008988 if (retval == FAIL || !bufref_valid(&bufref))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008989 break;
8990 }
8991 }
8992
8993 check_cursor(); /* just in case lines got deleted */
8994}
8995
8996/*
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008997 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
8998 * return TRUE and advance *argp to after it.
8999 * Thus return TRUE when do_modelines() should be called.
9000 */
9001 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009002check_nomodeline(char_u **argp)
Bram Moolenaar60542ac2012-02-12 20:14:01 +01009003{
9004 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
9005 {
9006 *argp = skipwhite(*argp + 12);
9007 return FALSE;
9008 }
9009 return TRUE;
9010}
9011
9012/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009013 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009014 * Search for a visible window containing the current buffer. If there isn't
9015 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00009016 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009017 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009018 */
9019 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009020aucmd_prepbuf(
9021 aco_save_T *aco, /* structure to save values in */
9022 buf_T *buf) /* new curbuf */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009023{
9024 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009025 int save_ea;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02009026#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02009027 int save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02009028#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009029
9030 /* Find a window that is for the new buffer */
9031 if (buf == curbuf) /* be quick when buf is curbuf */
9032 win = curwin;
9033 else
Bram Moolenaar29323592016-07-24 22:04:11 +02009034 FOR_ALL_WINDOWS(win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009035 if (win->w_buffer == buf)
9036 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009037
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009038 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
9039 * back to using the current window. */
9040 if (win == NULL && aucmd_win == NULL)
9041 {
9042 win_alloc_aucmd_win();
9043 if (aucmd_win == NULL)
9044 win = curwin;
9045 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009046 if (win == NULL && aucmd_win_used)
9047 /* Strange recursive autocommand, fall back to using the current
9048 * window. Expect a few side effects... */
9049 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009050
9051 aco->save_curwin = curwin;
9052 aco->save_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009053 if (win != NULL)
9054 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009055 /* There is a window for "buf" in the current tab page, make it the
9056 * curwin. This is preferred, it has the least side effects (esp. if
9057 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009058 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009059 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009060 }
9061 else
9062 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009063 /* There is no window for "buf", use "aucmd_win". To minimize the side
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02009064 * effects, insert it in the current tab page.
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009065 * Anything related to a window (e.g., setting folds) may have
9066 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009067 aco->use_aucmd_win = TRUE;
9068 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00009069 aucmd_win->w_buffer = buf;
Bram Moolenaarcdddaa42010-06-07 23:07:44 +02009070 aucmd_win->w_s = &buf->b_s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009071 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00009072 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009073
9074 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
9075 * win_enter_ext(). */
Bram Moolenaard23a8232018-02-10 18:45:26 +01009076 VIM_CLEAR(aucmd_win->w_localdir);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009077 aco->globaldir = globaldir;
9078 globaldir = NULL;
9079
Bram Moolenaar071d4272004-06-13 20:20:40 +00009080
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009081 /* Split the current window, put the aucmd_win in the upper half.
9082 * We don't want the BufEnter or WinEnter autocommands. */
9083 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009084 make_snapshot(SNAP_AUCMD_IDX);
9085 save_ea = p_ea;
9086 p_ea = FALSE;
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02009087
Bram Moolenaar4033c552017-09-16 20:54:51 +02009088#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02009089 /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
9090 save_acd = p_acd;
9091 p_acd = FALSE;
Bram Moolenaar4033c552017-09-16 20:54:51 +02009092#endif
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02009093
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009094 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
9095 (void)win_comp_pos(); /* recompute window positions */
9096 p_ea = save_ea;
Bram Moolenaar4033c552017-09-16 20:54:51 +02009097#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02009098 p_acd = save_acd;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009099#endif
Bram Moolenaar4033c552017-09-16 20:54:51 +02009100 unblock_autocmds();
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00009101 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009102 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009103 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009104 aco->new_curwin = curwin;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009105 set_bufref(&aco->new_curbuf, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009106}
9107
9108/*
9109 * Cleanup after executing autocommands for a (hidden) buffer.
9110 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009111 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009112 */
9113 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009114aucmd_restbuf(
9115 aco_save_T *aco) /* structure holding saved values */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009116{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009117 int dummy;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009118
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009119 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009120 {
9121 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009122 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009123 * page. Do not trigger autocommands here. */
9124 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009125 if (curwin != aucmd_win)
9126 {
9127 tabpage_T *tp;
9128 win_T *wp;
9129
9130 FOR_ALL_TAB_WINDOWS(tp, wp)
9131 {
9132 if (wp == aucmd_win)
9133 {
9134 if (tp != curtab)
Bram Moolenaar49e649f2013-05-06 04:50:35 +02009135 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009136 win_goto(aucmd_win);
Bram Moolenaar28f29082012-02-11 23:45:37 +01009137 goto win_found;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009138 }
9139 }
9140 }
Bram Moolenaar28f29082012-02-11 23:45:37 +01009141win_found:
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009142
9143 /* Remove the window and frame from the tree of frames. */
9144 (void)winframe_remove(curwin, &dummy, NULL);
9145 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009146 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009147 last_status(FALSE); /* may need to remove last status line */
Bram Moolenaar8c752bd2017-03-19 17:09:56 +01009148
9149 if (!valid_tabpage_win(curtab))
9150 /* no valid window in current tabpage */
9151 close_tabpage(curtab);
9152
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009153 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
9154 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009155 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009156
9157 if (win_valid(aco->save_curwin))
9158 curwin = aco->save_curwin;
9159 else
9160 /* Hmm, original window disappeared. Just use the first one. */
9161 curwin = firstwin;
Bram Moolenaar4033c552017-09-16 20:54:51 +02009162#ifdef FEAT_EVAL
Bram Moolenaar429fa852013-04-15 12:27:36 +02009163 vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
9164 hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009165#endif
9166 curbuf = curwin->w_buffer;
9167
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009168 vim_free(globaldir);
9169 globaldir = aco->globaldir;
9170
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009171 /* the buffer contents may have changed */
9172 check_cursor();
9173 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
9174 {
9175 curwin->w_topline = curbuf->b_ml.ml_line_count;
9176#ifdef FEAT_DIFF
9177 curwin->w_topfill = 0;
9178#endif
9179 }
9180#if defined(FEAT_GUI)
9181 /* Hide the scrollbars from the aucmd_win and update. */
9182 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
9183 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
9184 gui_may_update_scrollbars();
9185#endif
9186 }
9187 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009188 {
9189 /* restore curwin */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009190 if (win_valid(aco->save_curwin))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009191 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009192 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009193 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009194 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009195 if (curwin == aco->new_curwin
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009196 && curbuf != aco->new_curbuf.br_buf
9197 && bufref_valid(&aco->new_curbuf)
9198 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009199 {
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009200# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
9201 if (curwin->w_s == &curbuf->b_s)
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009202 curwin->w_s = &aco->new_curbuf.br_buf->b_s;
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009203# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009204 --curbuf->b_nwindows;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009205 curbuf = aco->new_curbuf.br_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009206 curwin->w_buffer = curbuf;
9207 ++curbuf->b_nwindows;
9208 }
9209
9210 curwin = aco->save_curwin;
9211 curbuf = curwin->w_buffer;
Bram Moolenaar371932a2014-09-09 16:59:38 +02009212 /* In case the autocommand move the cursor to a position that that
9213 * not exist in curbuf. */
9214 check_cursor();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009215 }
9216 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009217}
9218
9219static int autocmd_nested = FALSE;
9220
9221/*
9222 * Execute autocommands for "event" and file name "fname".
9223 * Return TRUE if some commands were executed.
9224 */
9225 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009226apply_autocmds(
9227 event_T event,
9228 char_u *fname, /* NULL or empty means use actual file name */
9229 char_u *fname_io, /* fname to use for <afile> on cmdline */
9230 int force, /* when TRUE, ignore autocmd_busy */
9231 buf_T *buf) /* buffer for <abuf> */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009232{
9233 return apply_autocmds_group(event, fname, fname_io, force,
9234 AUGROUP_ALL, buf, NULL);
9235}
9236
9237/*
9238 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
9239 * setting v:filearg.
9240 */
9241 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009242apply_autocmds_exarg(
9243 event_T event,
9244 char_u *fname,
9245 char_u *fname_io,
9246 int force,
9247 buf_T *buf,
9248 exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009249{
9250 return apply_autocmds_group(event, fname, fname_io, force,
9251 AUGROUP_ALL, buf, eap);
9252}
9253
9254/*
9255 * Like apply_autocmds(), but handles the caller's retval. If the script
9256 * processing is being aborted or if retval is FAIL when inside a try
9257 * conditional, no autocommands are executed. If otherwise the autocommands
9258 * cause the script to be aborted, retval is set to FAIL.
9259 */
9260 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009261apply_autocmds_retval(
9262 event_T event,
9263 char_u *fname, /* NULL or empty means use actual file name */
9264 char_u *fname_io, /* fname to use for <afile> on cmdline */
9265 int force, /* when TRUE, ignore autocmd_busy */
9266 buf_T *buf, /* buffer for <abuf> */
9267 int *retval) /* pointer to caller's retval */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009268{
9269 int did_cmd;
9270
Bram Moolenaar1e015462005-09-25 22:16:38 +00009271#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009272 if (should_abort(*retval))
9273 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00009274#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009275
9276 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
9277 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00009278 if (did_cmd
9279#ifdef FEAT_EVAL
9280 && aborting()
9281#endif
9282 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00009283 *retval = FAIL;
9284 return did_cmd;
9285}
9286
Bram Moolenaard35f9712005-12-18 22:02:33 +00009287/*
9288 * Return TRUE when there is a CursorHold autocommand defined.
9289 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009290 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009291has_cursorhold(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009292{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009293 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
9294 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009295}
Bram Moolenaard35f9712005-12-18 22:02:33 +00009296
9297/*
9298 * Return TRUE if the CursorHold event can be triggered.
9299 */
9300 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009301trigger_cursorhold(void)
Bram Moolenaard35f9712005-12-18 22:02:33 +00009302{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009303 int state;
9304
Bram Moolenaar05334432011-07-20 18:29:39 +02009305 if (!did_cursorhold
9306 && has_cursorhold()
9307 && !Recording
9308 && typebuf.tb_len == 0
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00009309#ifdef FEAT_INS_EXPAND
9310 && !ins_compl_active()
9311#endif
9312 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00009313 {
9314 state = get_real_state();
9315 if (state == NORMAL_BUSY || (state & INSERT) != 0)
9316 return TRUE;
9317 }
9318 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00009319}
Bram Moolenaar754b5602006-02-09 23:53:20 +00009320
9321/*
9322 * Return TRUE when there is a CursorMoved autocommand defined.
9323 */
9324 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009325has_cursormoved(void)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009326{
9327 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
9328}
9329
9330/*
9331 * Return TRUE when there is a CursorMovedI autocommand defined.
9332 */
9333 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009334has_cursormovedI(void)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009335{
9336 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
9337}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009338
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009339/*
Bram Moolenaar186628f2013-03-19 13:33:23 +01009340 * Return TRUE when there is a TextChanged autocommand defined.
9341 */
9342 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009343has_textchanged(void)
Bram Moolenaar186628f2013-03-19 13:33:23 +01009344{
9345 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
9346}
9347
9348/*
9349 * Return TRUE when there is a TextChangedI autocommand defined.
9350 */
9351 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009352has_textchangedI(void)
Bram Moolenaar186628f2013-03-19 13:33:23 +01009353{
9354 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
9355}
9356
9357/*
Bram Moolenaar5a093432018-02-10 18:15:19 +01009358 * Return TRUE when there is a TextChangedP autocommand defined.
9359 */
9360 int
9361has_textchangedP(void)
9362{
9363 return (first_autopat[(int)EVENT_TEXTCHANGEDP] != NULL);
9364}
9365
9366/*
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009367 * Return TRUE when there is an InsertCharPre autocommand defined.
9368 */
9369 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009370has_insertcharpre(void)
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009371{
9372 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
9373}
9374
Bram Moolenaard5005162014-08-22 23:05:54 +02009375/*
9376 * Return TRUE when there is an CmdUndefined autocommand defined.
9377 */
9378 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009379has_cmdundefined(void)
Bram Moolenaard5005162014-08-22 23:05:54 +02009380{
9381 return (first_autopat[(int)EVENT_CMDUNDEFINED] != NULL);
9382}
9383
9384/*
9385 * Return TRUE when there is an FuncUndefined autocommand defined.
9386 */
9387 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009388has_funcundefined(void)
Bram Moolenaard5005162014-08-22 23:05:54 +02009389{
9390 return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
9391}
9392
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009393/*
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01009394 * Return TRUE when there is a TextYankPost autocommand defined.
9395 */
9396 int
9397has_textyankpost(void)
9398{
9399 return (first_autopat[(int)EVENT_TEXTYANKPOST] != NULL);
9400}
9401
9402/*
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02009403 * Execute autocommands for "event" and file name "fname".
9404 * Return TRUE if some commands were executed.
9405 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009406 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009407apply_autocmds_group(
9408 event_T event,
9409 char_u *fname, /* NULL or empty means use actual file name */
9410 char_u *fname_io, /* fname to use for <afile> on cmdline, NULL means
Bram Moolenaar071d4272004-06-13 20:20:40 +00009411 use fname */
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009412 int force, /* when TRUE, ignore autocmd_busy */
9413 int group, /* group ID, or AUGROUP_ALL */
9414 buf_T *buf, /* buffer for <abuf> */
9415 exarg_T *eap) /* command arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009416{
9417 char_u *sfname = NULL; /* short file name */
9418 char_u *tail;
9419 int save_changed;
9420 buf_T *old_curbuf;
9421 int retval = FALSE;
9422 char_u *save_sourcing_name;
9423 linenr_T save_sourcing_lnum;
9424 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009425 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009426 int save_autocmd_bufnr;
9427 char_u *save_autocmd_match;
9428 int save_autocmd_busy;
9429 int save_autocmd_nested;
9430 static int nesting = 0;
9431 AutoPatCmd patcmd;
9432 AutoPat *ap;
9433#ifdef FEAT_EVAL
9434 scid_T save_current_SID;
9435 void *save_funccalp;
9436 char_u *save_cmdarg;
9437 long save_cmdbang;
9438#endif
9439 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00009440#ifdef FEAT_PROFILE
9441 proftime_T wait_time;
9442#endif
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009443 int did_save_redobuff = FALSE;
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009444 save_redo_T save_redo;
Bram Moolenaarc9e9c712017-11-09 12:29:35 +01009445 int save_KeyTyped = KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009446
9447 /*
9448 * Quickly return if there are no autocommands for this event or
9449 * autocommands are blocked.
9450 */
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02009451 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
9452 || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009453 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009454
9455 /*
9456 * When autocommands are busy, new autocommands are only executed when
9457 * explicitly enabled with the "nested" flag.
9458 */
9459 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009460 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009461
9462#ifdef FEAT_EVAL
9463 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00009464 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00009465 * occurred or an exception was thrown but not caught.
9466 */
9467 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009468 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009469#endif
9470
9471 /*
9472 * FileChangedShell never nests, because it can create an endless loop.
9473 */
Bram Moolenaar56718732006-03-15 22:53:57 +00009474 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
9475 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009476 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009477
9478 /*
9479 * Ignore events in 'eventignore'.
9480 */
9481 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009482 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009483
9484 /*
9485 * Allow nesting of autocommands, but restrict the depth, because it's
9486 * possible to create an endless loop.
9487 */
9488 if (nesting == 10)
9489 {
9490 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009491 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009492 }
9493
9494 /*
9495 * Check if these autocommands are disabled. Used when doing ":all" or
9496 * ":ball".
9497 */
9498 if ( (autocmd_no_enter
9499 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
9500 || (autocmd_no_leave
9501 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009502 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009503
9504 /*
9505 * Save the autocmd_* variables and info about the current buffer.
9506 */
9507 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009508 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009509 save_autocmd_bufnr = autocmd_bufnr;
9510 save_autocmd_match = autocmd_match;
9511 save_autocmd_busy = autocmd_busy;
9512 save_autocmd_nested = autocmd_nested;
9513 save_changed = curbuf->b_changed;
9514 old_curbuf = curbuf;
9515
9516 /*
9517 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00009518 * Make a copy to avoid that changing a buffer name or directory makes it
9519 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009520 */
9521 if (fname_io == NULL)
9522 {
Bram Moolenaar53744302015-07-17 17:38:22 +02009523 if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET)
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009524 autocmd_fname = NULL;
Bram Moolenaarfaf29d72017-07-09 11:07:16 +02009525 else if (fname != NULL && !ends_excmd(*fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009526 autocmd_fname = fname;
9527 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009528 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009529 else
9530 autocmd_fname = NULL;
9531 }
9532 else
9533 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009534 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009535 autocmd_fname = vim_strsave(autocmd_fname);
9536 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009537
9538 /*
9539 * Set the buffer number to be used for <abuf>.
9540 */
9541 if (buf == NULL)
9542 autocmd_bufnr = 0;
9543 else
9544 autocmd_bufnr = buf->b_fnum;
9545
9546 /*
9547 * When the file name is NULL or empty, use the file name of buffer "buf".
9548 * Always use the full path of the file name to match with, in case
9549 * "allow_dirs" is set.
9550 */
9551 if (fname == NULL || *fname == NUL)
9552 {
9553 if (buf == NULL)
9554 fname = NULL;
9555 else
9556 {
9557#ifdef FEAT_SYN_HL
9558 if (event == EVENT_SYNTAX)
9559 fname = buf->b_p_syn;
9560 else
9561#endif
9562 if (event == EVENT_FILETYPE)
9563 fname = buf->b_p_ft;
9564 else
9565 {
9566 if (buf->b_sfname != NULL)
9567 sfname = vim_strsave(buf->b_sfname);
9568 fname = buf->b_ffname;
9569 }
9570 }
9571 if (fname == NULL)
9572 fname = (char_u *)"";
9573 fname = vim_strsave(fname); /* make a copy, so we can change it */
9574 }
9575 else
9576 {
9577 sfname = vim_strsave(fname);
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009578 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
Bram Moolenaarb7407d32018-02-03 17:36:27 +01009579 * ColorScheme, QuickFixCmd* or DirChanged */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009580 if (event == EVENT_FILETYPE
9581 || event == EVENT_SYNTAX
Bram Moolenaar5135d462009-04-29 16:03:38 +00009582 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009583 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009584 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009585 || event == EVENT_QUICKFIXCMDPRE
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009586 || event == EVENT_COLORSCHEME
Bram Moolenaar53744302015-07-17 17:38:22 +02009587 || event == EVENT_OPTIONSET
Bram Moolenaarb7407d32018-02-03 17:36:27 +01009588 || event == EVENT_QUICKFIXCMDPOST
9589 || event == EVENT_DIRCHANGED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009590 fname = vim_strsave(fname);
9591 else
9592 fname = FullName_save(fname, FALSE);
9593 }
9594 if (fname == NULL) /* out of memory */
9595 {
9596 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009597 retval = FALSE;
9598 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009599 }
9600
9601#ifdef BACKSLASH_IN_FILENAME
9602 /*
9603 * Replace all backslashes with forward slashes. This makes the
9604 * autocommand patterns portable between Unix and MS-DOS.
9605 */
9606 if (sfname != NULL)
9607 forward_slash(sfname);
9608 forward_slash(fname);
9609#endif
9610
9611#ifdef VMS
9612 /* remove version for correct match */
9613 if (sfname != NULL)
9614 vms_remove_version(sfname);
9615 vms_remove_version(fname);
9616#endif
9617
9618 /*
9619 * Set the name to be used for <amatch>.
9620 */
9621 autocmd_match = fname;
9622
9623
9624 /* Don't redraw while doing auto commands. */
9625 ++RedrawingDisabled;
9626 save_sourcing_name = sourcing_name;
9627 sourcing_name = NULL; /* don't free this one */
9628 save_sourcing_lnum = sourcing_lnum;
9629 sourcing_lnum = 0; /* no line number here */
9630
9631#ifdef FEAT_EVAL
9632 save_current_SID = current_SID;
9633
Bram Moolenaar05159a02005-02-26 23:04:13 +00009634# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009635 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009636 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9637# endif
9638
Bram Moolenaar071d4272004-06-13 20:20:40 +00009639 /* Don't use local function variables, if called from a function */
9640 save_funccalp = save_funccal();
9641#endif
9642
9643 /*
9644 * When starting to execute autocommands, save the search patterns.
9645 */
9646 if (!autocmd_busy)
9647 {
9648 save_search_patterns();
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01009649#ifdef FEAT_INS_EXPAND
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009650 if (!ins_compl_active())
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01009651#endif
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009652 {
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009653 saveRedobuff(&save_redo);
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009654 did_save_redobuff = TRUE;
9655 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009656 did_filetype = keep_filetype;
9657 }
9658
9659 /*
9660 * Note that we are applying autocmds. Some commands need to know.
9661 */
9662 autocmd_busy = TRUE;
9663 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9664 ++nesting; /* see matching decrement below */
9665
9666 /* Remember that FileType was triggered. Used for did_filetype(). */
9667 if (event == EVENT_FILETYPE)
9668 did_filetype = TRUE;
9669
9670 tail = gettail(fname);
9671
9672 /* Find first autocommand that matches */
9673 patcmd.curpat = first_autopat[(int)event];
9674 patcmd.nextcmd = NULL;
9675 patcmd.group = group;
9676 patcmd.fname = fname;
9677 patcmd.sfname = sfname;
9678 patcmd.tail = tail;
9679 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009680 patcmd.arg_bufnr = autocmd_bufnr;
9681 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009682 auto_next_pat(&patcmd, FALSE);
9683
9684 /* found one, start executing the autocommands */
9685 if (patcmd.curpat != NULL)
9686 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009687 /* add to active_apc_list */
9688 patcmd.next = active_apc_list;
9689 active_apc_list = &patcmd;
9690
Bram Moolenaar071d4272004-06-13 20:20:40 +00009691#ifdef FEAT_EVAL
9692 /* set v:cmdarg (only when there is a matching pattern) */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02009693 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009694 if (eap != NULL)
9695 {
9696 save_cmdarg = set_cmdarg(eap, NULL);
9697 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9698 }
9699 else
9700 save_cmdarg = NULL; /* avoid gcc warning */
9701#endif
9702 retval = TRUE;
9703 /* mark the last pattern, to avoid an endless loop when more patterns
9704 * are added when executing autocommands */
9705 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9706 ap->last = FALSE;
9707 ap->last = TRUE;
9708 check_lnums(TRUE); /* make sure cursor and topline are valid */
9709 do_cmdline(NULL, getnextac, (void *)&patcmd,
9710 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9711#ifdef FEAT_EVAL
9712 if (eap != NULL)
9713 {
9714 (void)set_cmdarg(NULL, save_cmdarg);
9715 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9716 }
9717#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009718 /* delete from active_apc_list */
9719 if (active_apc_list == &patcmd) /* just in case */
9720 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009721 }
9722
9723 --RedrawingDisabled;
9724 autocmd_busy = save_autocmd_busy;
9725 filechangeshell_busy = FALSE;
9726 autocmd_nested = save_autocmd_nested;
9727 vim_free(sourcing_name);
9728 sourcing_name = save_sourcing_name;
9729 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009730 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009731 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009732 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009733 autocmd_bufnr = save_autocmd_bufnr;
9734 autocmd_match = save_autocmd_match;
9735#ifdef FEAT_EVAL
9736 current_SID = save_current_SID;
9737 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00009738# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009739 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009740 prof_child_exit(&wait_time);
9741# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009742#endif
Bram Moolenaarc9e9c712017-11-09 12:29:35 +01009743 KeyTyped = save_KeyTyped;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009744 vim_free(fname);
9745 vim_free(sfname);
9746 --nesting; /* see matching increment above */
9747
9748 /*
9749 * When stopping to execute autocommands, restore the search patterns and
Bram Moolenaar3be85852014-06-12 14:01:31 +02009750 * the redo buffer. Free any buffers in the au_pending_free_buf list and
9751 * free any windows in the au_pending_free_win list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009752 */
9753 if (!autocmd_busy)
9754 {
9755 restore_search_patterns();
Bram Moolenaarc51b02d2015-02-17 10:58:25 +01009756 if (did_save_redobuff)
Bram Moolenaard4863aa2017-04-07 19:50:12 +02009757 restoreRedobuff(&save_redo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009758 did_filetype = FALSE;
Bram Moolenaar4c7ab1b2014-04-06 20:45:43 +02009759 while (au_pending_free_buf != NULL)
9760 {
9761 buf_T *b = au_pending_free_buf->b_next;
9762 vim_free(au_pending_free_buf);
9763 au_pending_free_buf = b;
9764 }
Bram Moolenaar3be85852014-06-12 14:01:31 +02009765 while (au_pending_free_win != NULL)
9766 {
9767 win_T *w = au_pending_free_win->w_next;
9768 vim_free(au_pending_free_win);
9769 au_pending_free_win = w;
9770 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009771 }
9772
9773 /*
9774 * Some events don't set or reset the Changed flag.
9775 * Check if still in the same buffer!
9776 */
9777 if (curbuf == old_curbuf
9778 && (event == EVENT_BUFREADPOST
9779 || event == EVENT_BUFWRITEPOST
9780 || event == EVENT_FILEAPPENDPOST
9781 || event == EVENT_VIMLEAVE
9782 || event == EVENT_VIMLEAVEPRE))
9783 {
9784#ifdef FEAT_TITLE
9785 if (curbuf->b_changed != save_changed)
9786 need_maketitle = TRUE;
9787#endif
9788 curbuf->b_changed = save_changed;
9789 }
9790
9791 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009792
9793BYPASS_AU:
9794 /* When wiping out a buffer make sure all its buffer-local autocommands
9795 * are deleted. */
9796 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9797 aubuflocal_remove(buf);
9798
Bram Moolenaarc3691332016-04-20 12:49:49 +02009799 if (retval == OK && event == EVENT_FILETYPE)
9800 au_did_filetype = TRUE;
9801
Bram Moolenaar071d4272004-06-13 20:20:40 +00009802 return retval;
9803}
9804
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009805# ifdef FEAT_EVAL
9806static char_u *old_termresponse = NULL;
9807# endif
9808
9809/*
9810 * Block triggering autocommands until unblock_autocmd() is called.
9811 * Can be used recursively, so long as it's symmetric.
9812 */
9813 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009814block_autocmds(void)
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009815{
9816# ifdef FEAT_EVAL
9817 /* Remember the value of v:termresponse. */
9818 if (autocmd_blocked == 0)
9819 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9820# endif
9821 ++autocmd_blocked;
9822}
9823
9824 void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009825unblock_autocmds(void)
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009826{
9827 --autocmd_blocked;
9828
9829# ifdef FEAT_EVAL
9830 /* When v:termresponse was set while autocommands were blocked, trigger
9831 * the autocommands now. Esp. useful when executing a shell command
9832 * during startup (vimdiff). */
9833 if (autocmd_blocked == 0
9834 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9835 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9836# endif
9837}
9838
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009839 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009840is_autocmd_blocked(void)
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009841{
9842 return autocmd_blocked != 0;
9843}
9844
Bram Moolenaar071d4272004-06-13 20:20:40 +00009845/*
9846 * Find next autocommand pattern that matches.
9847 */
9848 static void
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009849auto_next_pat(
9850 AutoPatCmd *apc,
9851 int stop_at_last) /* stop when 'last' flag is set */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009852{
9853 AutoPat *ap;
9854 AutoCmd *cp;
9855 char_u *name;
9856 char *s;
9857
Bram Moolenaard23a8232018-02-10 18:45:26 +01009858 VIM_CLEAR(sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009859
9860 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9861 {
9862 apc->curpat = NULL;
9863
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009864 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009865 * the group matches. For buffer-local autocommands only check the
9866 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009867 if (ap->pat != NULL && ap->cmds != NULL
9868 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9869 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009870 /* execution-condition */
9871 if (ap->buflocal_nr == 0
Bram Moolenaardffa5b82014-11-19 16:38:07 +01009872 ? (match_file_pat(NULL, &ap->reg_prog, apc->fname,
Bram Moolenaar748bf032005-02-02 23:04:36 +00009873 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009874 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009875 {
9876 name = event_nr2name(apc->event);
9877 s = _("%s Auto commands for \"%s\"");
9878 sourcing_name = alloc((unsigned)(STRLEN(s)
9879 + STRLEN(name) + ap->patlen + 1));
9880 if (sourcing_name != NULL)
9881 {
9882 sprintf((char *)sourcing_name, s,
9883 (char *)name, (char *)ap->pat);
9884 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009885 {
9886 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009887 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009888 verbose_leave();
9889 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009890 }
9891
9892 apc->curpat = ap;
9893 apc->nextcmd = ap->cmds;
9894 /* mark last command */
9895 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9896 cp->last = FALSE;
9897 cp->last = TRUE;
9898 }
9899 line_breakcheck();
9900 if (apc->curpat != NULL) /* found a match */
9901 break;
9902 }
9903 if (stop_at_last && ap->last)
9904 break;
9905 }
9906}
9907
9908/*
9909 * Get next autocommand command.
9910 * Called by do_cmdline() to get the next line for ":if".
9911 * Returns allocated string, or NULL for end of autocommands.
9912 */
Bram Moolenaar21691f82012-12-05 19:13:18 +01009913 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009914getnextac(int c UNUSED, void *cookie, int indent UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009915{
9916 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9917 char_u *retval;
9918 AutoCmd *ac;
9919
9920 /* Can be called again after returning the last line. */
9921 if (acp->curpat == NULL)
9922 return NULL;
9923
9924 /* repeat until we find an autocommand to execute */
9925 for (;;)
9926 {
9927 /* skip removed commands */
9928 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9929 if (acp->nextcmd->last)
9930 acp->nextcmd = NULL;
9931 else
9932 acp->nextcmd = acp->nextcmd->next;
9933
9934 if (acp->nextcmd != NULL)
9935 break;
9936
9937 /* at end of commands, find next pattern that matches */
9938 if (acp->curpat->last)
9939 acp->curpat = NULL;
9940 else
9941 acp->curpat = acp->curpat->next;
9942 if (acp->curpat != NULL)
9943 auto_next_pat(acp, TRUE);
9944 if (acp->curpat == NULL)
9945 return NULL;
9946 }
9947
9948 ac = acp->nextcmd;
9949
9950 if (p_verbose >= 9)
9951 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009952 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009953 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009954 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009955 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009956 }
9957 retval = vim_strsave(ac->cmd);
9958 autocmd_nested = ac->nested;
9959#ifdef FEAT_EVAL
9960 current_SID = ac->scriptID;
9961#endif
9962 if (ac->last)
9963 acp->nextcmd = NULL;
9964 else
9965 acp->nextcmd = ac->next;
9966 return retval;
9967}
9968
9969/*
9970 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009971 * To account for buffer-local autocommands, function needs to know
9972 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009973 */
9974 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +01009975has_autocmd(event_T event, char_u *sfname, buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009976{
9977 AutoPat *ap;
9978 char_u *fname;
9979 char_u *tail = gettail(sfname);
9980 int retval = FALSE;
9981
9982 fname = FullName_save(sfname, FALSE);
9983 if (fname == NULL)
9984 return FALSE;
9985
9986#ifdef BACKSLASH_IN_FILENAME
9987 /*
9988 * Replace all backslashes with forward slashes. This makes the
9989 * autocommand patterns portable between Unix and MS-DOS.
9990 */
9991 sfname = vim_strsave(sfname);
9992 if (sfname != NULL)
9993 forward_slash(sfname);
9994 forward_slash(fname);
9995#endif
9996
9997 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9998 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009999 && (ap->buflocal_nr == 0
Bram Moolenaardffa5b82014-11-19 16:38:07 +010010000 ? match_file_pat(NULL, &ap->reg_prog,
Bram Moolenaar748bf032005-02-02 23:04:36 +000010001 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000010002 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010003 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010004 {
10005 retval = TRUE;
10006 break;
10007 }
10008
10009 vim_free(fname);
10010#ifdef BACKSLASH_IN_FILENAME
10011 vim_free(sfname);
10012#endif
10013
10014 return retval;
10015}
10016
10017#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
10018/*
10019 * Function given to ExpandGeneric() to obtain the list of autocommand group
10020 * names.
10021 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010022 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010023get_augroup_name(expand_T *xp UNUSED, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010024{
10025 if (idx == augroups.ga_len) /* add "END" add the end */
10026 return (char_u *)"END";
10027 if (idx >= augroups.ga_len) /* end of list */
10028 return NULL;
Bram Moolenaarb62cc362016-09-03 16:43:53 +020010029 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup())
Bram Moolenaarf2c4c392016-07-29 20:50:24 +020010030 /* skip deleted entries */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010031 return (char_u *)"";
10032 return AUGROUP_NAME(idx); /* return a name */
10033}
10034
10035static int include_groups = FALSE;
10036
10037 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010038set_context_in_autocmd(
10039 expand_T *xp,
10040 char_u *arg,
10041 int doautocmd) /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042{
10043 char_u *p;
10044 int group;
10045
10046 /* check for a group name, skip it if present */
10047 include_groups = FALSE;
10048 p = arg;
10049 group = au_get_grouparg(&arg);
10050 if (group == AUGROUP_ERROR)
10051 return NULL;
10052 /* If there only is a group name that's what we expand. */
Bram Moolenaar1c465442017-03-12 20:10:05 +010010053 if (*arg == NUL && group != AUGROUP_ALL && !VIM_ISWHITE(arg[-1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010054 {
10055 arg = p;
10056 group = AUGROUP_ALL;
10057 }
10058
10059 /* skip over event name */
Bram Moolenaar1c465442017-03-12 20:10:05 +010010060 for (p = arg; *p != NUL && !VIM_ISWHITE(*p); ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010061 if (*p == ',')
10062 arg = p + 1;
10063 if (*p == NUL)
10064 {
10065 if (group == AUGROUP_ALL)
10066 include_groups = TRUE;
10067 xp->xp_context = EXPAND_EVENTS; /* expand event name */
10068 xp->xp_pattern = arg;
10069 return NULL;
10070 }
10071
10072 /* skip over pattern */
10073 arg = skipwhite(p);
Bram Moolenaar1c465442017-03-12 20:10:05 +010010074 while (*arg && (!VIM_ISWHITE(*arg) || arg[-1] == '\\'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010075 arg++;
10076 if (*arg)
10077 return arg; /* expand (next) command */
10078
10079 if (doautocmd)
10080 xp->xp_context = EXPAND_FILES; /* expand file names */
10081 else
10082 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
10083 return NULL;
10084}
10085
10086/*
10087 * Function given to ExpandGeneric() to obtain the list of event names.
10088 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010089 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010090get_event_name(expand_T *xp UNUSED, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010091{
10092 if (idx < augroups.ga_len) /* First list group names, if wanted */
10093 {
Bram Moolenaarf2c4c392016-07-29 20:50:24 +020010094 if (!include_groups || AUGROUP_NAME(idx) == NULL
Bram Moolenaarb62cc362016-09-03 16:43:53 +020010095 || AUGROUP_NAME(idx) == get_deleted_augroup())
Bram Moolenaar071d4272004-06-13 20:20:40 +000010096 return (char_u *)""; /* skip deleted entries */
10097 return AUGROUP_NAME(idx); /* return a name */
10098 }
10099 return (char_u *)event_names[idx - augroups.ga_len].name;
10100}
10101
10102#endif /* FEAT_CMDL_COMPL */
10103
10104/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010105 * Return TRUE if autocmd is supported.
10106 */
10107 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010108autocmd_supported(char_u *name)
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010109{
10110 char_u *p;
10111
10112 return (event_name2nr(name, &p) != NUM_EVENTS);
10113}
10114
10115/*
Bram Moolenaar195d6352005-12-19 22:08:24 +000010116 * Return TRUE if an autocommand is defined for a group, event and
10117 * pattern: The group can be omitted to accept any group. "event" and "pattern"
10118 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
10119 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
10120 * Used for:
10121 * exists("#Group") or
10122 * exists("#Group#Event") or
10123 * exists("#Group#Event#pat") or
10124 * exists("#Event") or
10125 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +000010126 */
10127 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010128au_exists(char_u *arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010129{
Bram Moolenaar195d6352005-12-19 22:08:24 +000010130 char_u *arg_save;
10131 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010132 char_u *event_name;
10133 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +000010134 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010135 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010136 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +000010137 int group;
10138 int retval = FALSE;
10139
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010140 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +000010141 arg_save = vim_strsave(arg);
10142 if (arg_save == NULL)
10143 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010144 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +000010145 if (p != NULL)
10146 *p++ = NUL;
10147
10148 /* First, look for an autocmd group name */
10149 group = au_find_group(arg_save);
10150 if (group == AUGROUP_ERROR)
10151 {
10152 /* Didn't match a group name, assume the first argument is an event. */
10153 group = AUGROUP_ALL;
10154 event_name = arg_save;
10155 }
10156 else
10157 {
10158 if (p == NULL)
10159 {
10160 /* "Group": group name is present and it's recognized */
10161 retval = TRUE;
10162 goto theend;
10163 }
10164
10165 /* Must be "Group#Event" or "Group#Event#pat". */
10166 event_name = p;
10167 p = vim_strchr(event_name, '#');
10168 if (p != NULL)
10169 *p++ = NUL; /* "Group#Event#pat" */
10170 }
10171
10172 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010173
10174 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010175 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010176
10177 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +000010178 if (event == NUM_EVENTS)
10179 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010180
10181 /* Find the first autocommand for this event.
10182 * If there isn't any, return FALSE;
10183 * If there is one and no pattern given, return TRUE; */
10184 ap = first_autopat[(int)event];
10185 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +000010186 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010187
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010188 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
10189 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010190 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010191 buflocal_buf = curbuf;
10192
Bram Moolenaar071d4272004-06-13 20:20:40 +000010193 /* Check if there is an autocommand with the given pattern. */
10194 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010195 /* only use a pattern when it has not been removed and has commands. */
10196 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010197 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +000010198 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010199 && (pattern == NULL
10200 || (buflocal_buf == NULL
10201 ? fnamecmp(ap->pat, pattern) == 0
10202 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +000010203 {
10204 retval = TRUE;
10205 break;
10206 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010207
Bram Moolenaar195d6352005-12-19 22:08:24 +000010208theend:
10209 vim_free(arg_save);
10210 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010211}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010212
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010213#else /* FEAT_AUTOCMD */
10214
10215/*
10216 * Prepare for executing commands for (hidden) buffer "buf".
10217 * This is the non-autocommand version, it simply saves "curbuf" and sets
10218 * "curbuf" and "curwin" to match "buf".
10219 */
10220 void
Bram Moolenaard14e00e2016-01-31 17:30:51 +010010221aucmd_prepbuf(
10222 aco_save_T *aco, /* structure to save values in */
10223 buf_T *buf) /* new curbuf */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010224{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010225 aco->save_curbuf = curbuf;
10226 --curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010227 curbuf = buf;
10228 curwin->w_buffer = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010229 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010230}
10231
10232/*
10233 * Restore after executing commands for a (hidden) buffer.
10234 * This is the non-autocommand version.
10235 */
10236 void
Bram Moolenaard14e00e2016-01-31 17:30:51 +010010237aucmd_restbuf(
10238 aco_save_T *aco) /* structure holding saved values */
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010239{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010240 --curbuf->b_nwindows;
10241 curbuf = aco->save_curbuf;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010242 curwin->w_buffer = curbuf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010243 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010244}
10245
Bram Moolenaar071d4272004-06-13 20:20:40 +000010246#endif /* FEAT_AUTOCMD */
10247
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010248
Bram Moolenaar071d4272004-06-13 20:20:40 +000010249#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
10250/*
Bram Moolenaar748bf032005-02-02 23:04:36 +000010251 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
10252 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
10253 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010254 * Used for autocommands and 'wildignore'.
10255 * Returns TRUE if there is a match, FALSE otherwise.
10256 */
Bram Moolenaardffa5b82014-11-19 16:38:07 +010010257 static int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010258match_file_pat(
10259 char_u *pattern, /* pattern to match with */
10260 regprog_T **prog, /* pre-compiled regprog or NULL */
10261 char_u *fname, /* full path of file name */
10262 char_u *sfname, /* short file name or NULL */
10263 char_u *tail, /* tail of path */
10264 int allow_dirs) /* allow matching with dir */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010265{
10266 regmatch_T regmatch;
10267 int result = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010268
Bram Moolenaar71afbfe2013-03-19 16:49:16 +010010269 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010270 if (prog != NULL)
10271 regmatch.regprog = *prog;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010272 else
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010273 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010274
10275 /*
10276 * Try for a match with the pattern with:
10277 * 1. the full file name, when the pattern has a '/'.
10278 * 2. the short file name, when the pattern has a '/'.
10279 * 3. the tail of the file name, when the pattern has no '/'.
10280 */
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010281 if (regmatch.regprog != NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +000010282 && ((allow_dirs
10283 && (vim_regexec(&regmatch, fname, (colnr_T)0)
10284 || (sfname != NULL
10285 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010286 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0))))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010287 result = TRUE;
10288
Bram Moolenaardffa5b82014-11-19 16:38:07 +010010289 if (prog != NULL)
10290 *prog = regmatch.regprog;
10291 else
Bram Moolenaar473de612013-06-08 18:19:48 +020010292 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010293 return result;
10294}
10295#endif
10296
10297#if defined(FEAT_WILDIGN) || defined(PROTO)
10298/*
10299 * Return TRUE if a file matches with a pattern in "list".
10300 * "list" is a comma-separated list of patterns, like 'wildignore'.
10301 * "sfname" is the short file name or NULL, "ffname" the long file name.
10302 */
10303 int
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010304match_file_list(char_u *list, char_u *sfname, char_u *ffname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010305{
10306 char_u buf[100];
10307 char_u *tail;
10308 char_u *regpat;
10309 char allow_dirs;
10310 int match;
10311 char_u *p;
10312
10313 tail = gettail(sfname);
10314
10315 /* try all patterns in 'wildignore' */
10316 p = list;
10317 while (*p)
10318 {
10319 copy_option_part(&p, buf, 100, ",");
10320 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
10321 if (regpat == NULL)
10322 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +000010323 match = match_file_pat(regpat, NULL, ffname, sfname,
10324 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010325 vim_free(regpat);
10326 if (match)
10327 return TRUE;
10328 }
10329 return FALSE;
10330}
10331#endif
10332
10333/*
10334 * Convert the given pattern "pat" which has shell style wildcards in it, into
10335 * a regular expression, and return the result in allocated memory. If there
10336 * is a directory path separator to be matched, then TRUE is put in
10337 * allow_dirs, otherwise FALSE is put there -- webb.
10338 * Handle backslashes before special characters, like "\*" and "\ ".
10339 *
Bram Moolenaar071d4272004-06-13 20:20:40 +000010340 * Returns NULL when out of memory.
10341 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010342 char_u *
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010343file_pat_to_reg_pat(
10344 char_u *pat,
10345 char_u *pat_end, /* first char after pattern or NULL */
10346 char *allow_dirs, /* Result passed back out in here */
10347 int no_bslash UNUSED) /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010348{
Bram Moolenaar49a6ed82015-01-07 14:43:39 +010010349 int size = 2; /* '^' at start, '$' at end */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010350 char_u *endp;
10351 char_u *reg_pat;
10352 char_u *p;
10353 int i;
10354 int nested = 0;
10355 int add_dollar = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010356
10357 if (allow_dirs != NULL)
10358 *allow_dirs = FALSE;
10359 if (pat_end == NULL)
10360 pat_end = pat + STRLEN(pat);
10361
Bram Moolenaar071d4272004-06-13 20:20:40 +000010362 for (p = pat; p < pat_end; p++)
10363 {
10364 switch (*p)
10365 {
10366 case '*':
10367 case '.':
10368 case ',':
10369 case '{':
10370 case '}':
10371 case '~':
10372 size += 2; /* extra backslash */
10373 break;
10374#ifdef BACKSLASH_IN_FILENAME
10375 case '\\':
10376 case '/':
10377 size += 4; /* could become "[\/]" */
10378 break;
10379#endif
10380 default:
10381 size++;
Bram Moolenaar2288afe2015-08-11 16:20:05 +020010382# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010383 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010384 {
10385 ++p;
10386 ++size;
10387 }
10388# endif
10389 break;
10390 }
10391 }
10392 reg_pat = alloc(size + 1);
10393 if (reg_pat == NULL)
10394 return NULL;
10395
Bram Moolenaar071d4272004-06-13 20:20:40 +000010396 i = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010397
10398 if (pat[0] == '*')
10399 while (pat[0] == '*' && pat < pat_end - 1)
10400 pat++;
10401 else
10402 reg_pat[i++] = '^';
10403 endp = pat_end - 1;
Bram Moolenaar8fee8782015-08-11 18:45:48 +020010404 if (endp >= pat && *endp == '*')
Bram Moolenaar071d4272004-06-13 20:20:40 +000010405 {
10406 while (endp - pat > 0 && *endp == '*')
10407 endp--;
10408 add_dollar = FALSE;
10409 }
10410 for (p = pat; *p && nested >= 0 && p <= endp; p++)
10411 {
10412 switch (*p)
10413 {
10414 case '*':
10415 reg_pat[i++] = '.';
10416 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +000010417 while (p[1] == '*') /* "**" matches like "*" */
10418 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010419 break;
10420 case '.':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010421 case '~':
10422 reg_pat[i++] = '\\';
10423 reg_pat[i++] = *p;
10424 break;
10425 case '?':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010426 reg_pat[i++] = '.';
10427 break;
10428 case '\\':
10429 if (p[1] == NUL)
10430 break;
10431#ifdef BACKSLASH_IN_FILENAME
10432 if (!no_bslash)
10433 {
10434 /* translate:
10435 * "\x" to "\\x" e.g., "dir\file"
10436 * "\*" to "\\.*" e.g., "dir\*.c"
10437 * "\?" to "\\." e.g., "dir\??.c"
10438 * "\+" to "\+" e.g., "fileX\+.c"
10439 */
10440 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
10441 && p[1] != '+')
10442 {
10443 reg_pat[i++] = '[';
10444 reg_pat[i++] = '\\';
10445 reg_pat[i++] = '/';
10446 reg_pat[i++] = ']';
10447 if (allow_dirs != NULL)
10448 *allow_dirs = TRUE;
10449 break;
10450 }
10451 }
10452#endif
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010453 /* Undo escaping from ExpandEscape():
10454 * foo\?bar -> foo?bar
10455 * foo\%bar -> foo%bar
10456 * foo\,bar -> foo,bar
10457 * foo\ bar -> foo bar
10458 * Don't unescape \, * and others that are also special in a
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010459 * regexp.
10460 * An escaped { must be unescaped since we use magic not
Bram Moolenaara946afe2013-08-02 15:22:39 +020010461 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010462 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010463 if (*++p == '?'
10464#ifdef BACKSLASH_IN_FILENAME
10465 && no_bslash
10466#endif
10467 )
10468 reg_pat[i++] = '?';
10469 else
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010470 if (*p == ',' || *p == '%' || *p == '#'
Bram Moolenaar2288afe2015-08-11 16:20:05 +020010471 || vim_isspace(*p) || *p == '{' || *p == '}')
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010472 reg_pat[i++] = *p;
Bram Moolenaara946afe2013-08-02 15:22:39 +020010473 else if (*p == '\\' && p[1] == '\\' && p[2] == '{')
10474 {
10475 reg_pat[i++] = '\\';
10476 reg_pat[i++] = '{';
10477 p += 2;
10478 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010479 else
10480 {
10481 if (allow_dirs != NULL && vim_ispathsep(*p)
10482#ifdef BACKSLASH_IN_FILENAME
10483 && (!no_bslash || *p != '\\')
10484#endif
10485 )
10486 *allow_dirs = TRUE;
10487 reg_pat[i++] = '\\';
10488 reg_pat[i++] = *p;
10489 }
10490 break;
10491#ifdef BACKSLASH_IN_FILENAME
10492 case '/':
10493 reg_pat[i++] = '[';
10494 reg_pat[i++] = '\\';
10495 reg_pat[i++] = '/';
10496 reg_pat[i++] = ']';
10497 if (allow_dirs != NULL)
10498 *allow_dirs = TRUE;
10499 break;
10500#endif
10501 case '{':
10502 reg_pat[i++] = '\\';
10503 reg_pat[i++] = '(';
10504 nested++;
10505 break;
10506 case '}':
10507 reg_pat[i++] = '\\';
10508 reg_pat[i++] = ')';
10509 --nested;
10510 break;
10511 case ',':
10512 if (nested)
10513 {
10514 reg_pat[i++] = '\\';
10515 reg_pat[i++] = '|';
10516 }
10517 else
10518 reg_pat[i++] = ',';
10519 break;
10520 default:
10521# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010522 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010523 reg_pat[i++] = *p++;
10524 else
10525# endif
10526 if (allow_dirs != NULL && vim_ispathsep(*p))
10527 *allow_dirs = TRUE;
10528 reg_pat[i++] = *p;
10529 break;
10530 }
10531 }
10532 if (add_dollar)
10533 reg_pat[i++] = '$';
10534 reg_pat[i] = NUL;
10535 if (nested != 0)
10536 {
10537 if (nested < 0)
10538 EMSG(_("E219: Missing {."));
10539 else
10540 EMSG(_("E220: Missing }."));
Bram Moolenaard23a8232018-02-10 18:45:26 +010010541 VIM_CLEAR(reg_pat);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010542 }
10543 return reg_pat;
10544}
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010545
10546#if defined(EINTR) || defined(PROTO)
10547/*
10548 * Version of read() that retries when interrupted by EINTR (possibly
10549 * by a SIGWINCH).
10550 */
10551 long
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010552read_eintr(int fd, void *buf, size_t bufsize)
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010553{
10554 long ret;
10555
10556 for (;;)
10557 {
10558 ret = vim_read(fd, buf, bufsize);
10559 if (ret >= 0 || errno != EINTR)
10560 break;
10561 }
10562 return ret;
10563}
10564
10565/*
10566 * Version of write() that retries when interrupted by EINTR (possibly
10567 * by a SIGWINCH).
10568 */
10569 long
Bram Moolenaar78c0b7d2016-01-30 15:52:46 +010010570write_eintr(int fd, void *buf, size_t bufsize)
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010571{
10572 long ret = 0;
10573 long wlen;
10574
10575 /* Repeat the write() so long it didn't fail, other than being interrupted
10576 * by a signal. */
10577 while (ret < (long)bufsize)
10578 {
Bram Moolenaar9c263032010-12-17 18:06:06 +010010579 wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010580 if (wlen < 0)
10581 {
10582 if (errno != EINTR)
10583 break;
10584 }
10585 else
10586 ret += wlen;
10587 }
10588 return ret;
10589}
10590#endif