blob: f8b384b9e9e18c0b458d34d7dcd738f3d90352dc [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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
27#ifdef FEAT_CRYPT
Bram Moolenaar40e6a712010-05-16 22:32:54 +020028/* crypt_magic[0] is pkzip crypt, crypt_magic[1] is sha2+blowfish */
Bram Moolenaarf50a2532010-05-21 15:36:08 +020029static char *crypt_magic[] = {"VimCrypt~01!", "VimCrypt~02!"};
30static char crypt_magic_head[] = "VimCrypt~";
31# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
Bram Moolenaar80794b12010-06-13 05:20:42 +020032
33/* For blowfish, after the magic header, we store 8 bytes of salt and then 8
34 * bytes of seed (initialisation vector). */
35static int crypt_salt_len[] = {0, 8};
Bram Moolenaarf50a2532010-05-21 15:36:08 +020036static int crypt_seed_len[] = {0, 8};
Bram Moolenaar80794b12010-06-13 05:20:42 +020037#define CRYPT_SALT_LEN_MAX 8
Bram Moolenaar40e6a712010-05-16 22:32:54 +020038#define CRYPT_SEED_LEN_MAX 8
Bram Moolenaar071d4272004-06-13 20:20:40 +000039#endif
40
41/* Is there any system that doesn't have access()? */
Bram Moolenaar9372a112005-12-06 19:59:18 +000042#define USE_MCH_ACCESS
Bram Moolenaar071d4272004-06-13 20:20:40 +000043
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +000044#if defined(sun) && defined(S_ISCHR)
45# define OPEN_CHR_FILES
46static int is_dev_fd_file(char_u *fname);
47#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000048#ifdef FEAT_MBYTE
49static char_u *next_fenc __ARGS((char_u **pp));
50# ifdef FEAT_EVAL
51static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));
52# endif
53#endif
54#ifdef FEAT_VIMINFO
55static void check_marks_read __ARGS((void));
56#endif
57#ifdef FEAT_CRYPT
Bram Moolenaar49771f42010-07-20 17:32:38 +020058static int crypt_method_from_magic __ARGS((char *ptr, int len));
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +020059static char_u *check_for_cryptkey __ARGS((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 +000060#endif
61#ifdef UNIX
62static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
63#endif
Bram Moolenaar2d3f4892006-01-20 23:02:51 +000064static int set_rw_fname __ARGS((char_u *fname, char_u *sfname));
Bram Moolenaar071d4272004-06-13 20:20:40 +000065static int msg_add_fileformat __ARGS((int eol_type));
Bram Moolenaar071d4272004-06-13 20:20:40 +000066static void msg_add_eol __ARGS((void));
67static int check_mtime __ARGS((buf_T *buf, struct stat *s));
68static int time_differs __ARGS((long t1, long t2));
69#ifdef FEAT_AUTOCMD
Bram Moolenaar754b5602006-02-09 23:53:20 +000070static int apply_autocmds_exarg __ARGS((event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap));
Bram Moolenaar70836c82006-02-20 21:28:49 +000071static int au_find_group __ARGS((char_u *name));
72
73# define AUGROUP_DEFAULT -1 /* default autocmd group */
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +000074# define AUGROUP_ERROR -2 /* erroneous autocmd group */
Bram Moolenaar70836c82006-02-20 21:28:49 +000075# define AUGROUP_ALL -3 /* all autocmd groups */
Bram Moolenaar071d4272004-06-13 20:20:40 +000076#endif
77
78#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
79# define HAS_BW_FLAGS
80# define FIO_LATIN1 0x01 /* convert Latin1 */
81# define FIO_UTF8 0x02 /* convert UTF-8 */
82# define FIO_UCS2 0x04 /* convert UCS-2 */
83# define FIO_UCS4 0x08 /* convert UCS-4 */
84# define FIO_UTF16 0x10 /* convert UTF-16 */
85# ifdef WIN3264
86# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
87# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
88# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
89# endif
90# ifdef MACOS_X
91# define FIO_MACROMAN 0x20 /* convert MacRoman */
92# endif
93# define FIO_ENDIAN_L 0x80 /* little endian */
94# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
95# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
96# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
97# define FIO_ALL -1 /* allow all formats */
98#endif
99
100/* When converting, a read() or write() may leave some bytes to be converted
101 * for the next call. The value is guessed... */
102#define CONV_RESTLEN 30
103
104/* We have to guess how much a sequence of bytes may expand when converting
105 * with iconv() to be able to allocate a buffer. */
106#define ICONV_MULT 8
107
108/*
109 * Structure to pass arguments from buf_write() to buf_write_bytes().
110 */
111struct bw_info
112{
113 int bw_fd; /* file descriptor */
114 char_u *bw_buf; /* buffer with data to be written */
Bram Moolenaard089d9b2007-09-30 12:02:55 +0000115 int bw_len; /* length of data */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000116#ifdef HAS_BW_FLAGS
117 int bw_flags; /* FIO_ flags */
118#endif
119#ifdef FEAT_MBYTE
120 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
121 int bw_restlen; /* nr of bytes in bw_rest[] */
122 int bw_first; /* first write call */
123 char_u *bw_conv_buf; /* buffer for writing converted chars */
124 int bw_conv_buflen; /* size of bw_conv_buf */
125 int bw_conv_error; /* set for conversion error */
Bram Moolenaar32b485f2009-07-29 16:06:27 +0000126 linenr_T bw_conv_error_lnum; /* first line with error or zero */
127 linenr_T bw_start_lnum; /* line number at start of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000128# ifdef USE_ICONV
129 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
130# endif
131#endif
132};
133
134static int buf_write_bytes __ARGS((struct bw_info *ip));
135
136#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000137static linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +0000139static int need_conversion __ARGS((char_u *fenc));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140static int get_fio_flags __ARGS((char_u *ptr));
141static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
142static int make_bom __ARGS((char_u *buf, char_u *name));
143# ifdef WIN3264
144static int get_win_fio_flags __ARGS((char_u *ptr));
145# endif
146# ifdef MACOS_X
147static int get_mac_fio_flags __ARGS((char_u *ptr));
148# endif
149#endif
150static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000151#ifdef TEMPDIRNAMES
Bram Moolenaareaf03392009-11-17 11:08:52 +0000152static void vim_settempdir __ARGS((char_u *tempdir));
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000153#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000154#ifdef FEAT_AUTOCMD
155static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
156#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000157
Bram Moolenaar071d4272004-06-13 20:20:40 +0000158 void
159filemess(buf, name, s, attr)
160 buf_T *buf;
161 char_u *name;
162 char_u *s;
163 int attr;
164{
165 int msg_scroll_save;
166
167 if (msg_silent != 0)
168 return;
169 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
170 /* If it's extremely long, truncate it. */
171 if (STRLEN(IObuff) > IOSIZE - 80)
172 IObuff[IOSIZE - 80] = NUL;
173 STRCAT(IObuff, s);
174 /*
175 * For the first message may have to start a new line.
176 * For further ones overwrite the previous one, reset msg_scroll before
177 * calling filemess().
178 */
179 msg_scroll_save = msg_scroll;
180 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
181 msg_scroll = FALSE;
182 if (!msg_scroll) /* wait a bit when overwriting an error msg */
183 check_for_delay(FALSE);
184 msg_start();
185 msg_scroll = msg_scroll_save;
186 msg_scrolled_ign = TRUE;
187 /* may truncate the message to avoid a hit-return prompt */
188 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
189 msg_clr_eos();
190 out_flush();
191 msg_scrolled_ign = FALSE;
192}
193
194/*
195 * Read lines from file "fname" into the buffer after line "from".
196 *
197 * 1. We allocate blocks with lalloc, as big as possible.
198 * 2. Each block is filled with characters from the file with a single read().
199 * 3. The lines are inserted in the buffer with ml_append().
200 *
201 * (caller must check that fname != NULL, unless READ_STDIN is used)
202 *
203 * "lines_to_skip" is the number of lines that must be skipped
204 * "lines_to_read" is the number of lines that are appended
205 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
206 *
207 * flags:
208 * READ_NEW starting to edit a new buffer
209 * READ_FILTER reading filter output
210 * READ_STDIN read from stdin instead of a file
211 * READ_BUFFER read from curbuf instead of a file (converting after reading
212 * stdin)
213 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
Bram Moolenaar59f931e2010-07-24 20:27:03 +0200214 * READ_KEEP_UNDO don't clear undo info or read it from a file
Bram Moolenaar071d4272004-06-13 20:20:40 +0000215 *
216 * return FAIL for failure, OK otherwise
217 */
218 int
219readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
220 char_u *fname;
221 char_u *sfname;
222 linenr_T from;
223 linenr_T lines_to_skip;
224 linenr_T lines_to_read;
225 exarg_T *eap; /* can be NULL! */
226 int flags;
227{
228 int fd = 0;
229 int newfile = (flags & READ_NEW);
230 int check_readonly;
231 int filtering = (flags & READ_FILTER);
232 int read_stdin = (flags & READ_STDIN);
233 int read_buffer = (flags & READ_BUFFER);
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000234 int set_options = newfile || read_buffer
235 || (eap != NULL && eap->read_edit);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000236 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
237 colnr_T read_buf_col = 0; /* next char to read from this line */
238 char_u c;
239 linenr_T lnum = from;
240 char_u *ptr = NULL; /* pointer into read buffer */
241 char_u *buffer = NULL; /* read buffer */
242 char_u *new_buffer = NULL; /* init to shut up gcc */
243 char_u *line_start = NULL; /* init to shut up gcc */
244 int wasempty; /* buffer was empty before reading */
245 colnr_T len;
246 long size = 0;
247 char_u *p;
Bram Moolenaar914703b2010-05-31 21:59:46 +0200248 off_t filesize = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249 int skip_read = FALSE;
250#ifdef FEAT_CRYPT
251 char_u *cryptkey = NULL;
Bram Moolenaarf50a2532010-05-21 15:36:08 +0200252 int did_ask_for_key = FALSE;
Bram Moolenaar4cf35c22011-02-25 16:52:17 +0100253 int crypt_method_used;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000254#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +0200255#ifdef FEAT_PERSISTENT_UNDO
256 context_sha256_T sha_ctx;
257 int read_undo_file = FALSE;
258#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259 int split = 0; /* number of split lines */
260#define UNKNOWN 0x0fffffff /* file size is unknown */
261 linenr_T linecnt;
262 int error = FALSE; /* errors encountered */
263 int ff_error = EOL_UNKNOWN; /* file format with errors */
264 long linerest = 0; /* remaining chars in line */
265#ifdef UNIX
266 int perm = 0;
267 int swap_mode = -1; /* protection bits for swap file */
268#else
269 int perm;
270#endif
271 int fileformat = 0; /* end-of-line format */
272 int keep_fileformat = FALSE;
273 struct stat st;
274 int file_readonly;
275 linenr_T skip_count = 0;
276 linenr_T read_count = 0;
277 int msg_save = msg_scroll;
278 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
279 * last read was missing the eol */
280 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
281 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
282 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
283 int file_rewind = FALSE;
284#ifdef FEAT_MBYTE
285 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000286 linenr_T conv_error = 0; /* line nr with conversion error */
287 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
289 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000290 int bad_char_behavior = BAD_REPLACE;
291 /* BAD_KEEP, BAD_DROP or character to
292 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000293 char_u *tmpname = NULL; /* name of 'charconvert' output file */
294 int fio_flags = 0;
295 char_u *fenc; /* fileencoding to use */
296 int fenc_alloced; /* fenc_next is in allocated memory */
297 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
298 int advance_fenc = FALSE;
299 long real_size = 0;
300# ifdef USE_ICONV
301 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
302# ifdef FEAT_EVAL
303 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
304 'charconvert' next */
305# endif
306# endif
307 int converted = FALSE; /* TRUE if conversion done */
308 int notconverted = FALSE; /* TRUE if conversion wanted but it
309 wasn't possible */
310 char_u conv_rest[CONV_RESTLEN];
311 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
312#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000313#ifdef FEAT_AUTOCMD
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200314 buf_T *old_curbuf;
315 char_u *old_b_ffname;
316 char_u *old_b_fname;
317 int using_b_ffname;
318 int using_b_fname;
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000319#endif
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200320
Bram Moolenaarcab35ad2011-02-15 17:39:22 +0100321 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322
323 /*
324 * If there is no file name yet, use the one for the read file.
325 * BF_NOTEDITED is set to reflect this.
326 * Don't do this for a read from a filter.
327 * Only do this when 'cpoptions' contains the 'f' flag.
328 */
329 if (curbuf->b_ffname == NULL
330 && !filtering
331 && fname != NULL
332 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
333 && !(flags & READ_DUMMY))
334 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000335 if (set_rw_fname(fname, sfname) == FAIL)
336 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337 }
338
Bram Moolenaarbb3d5dc2010-08-14 14:32:54 +0200339#ifdef FEAT_AUTOCMD
340 /* Remember the initial values of curbuf, curbuf->b_ffname and
341 * curbuf->b_fname to detect whether they are altered as a result of
342 * executing nasty autocommands. Also check if "fname" and "sfname"
343 * point to one of these values. */
344 old_curbuf = curbuf;
345 old_b_ffname = curbuf->b_ffname;
346 old_b_fname = curbuf->b_fname;
347 using_b_ffname = (fname == curbuf->b_ffname)
348 || (sfname == curbuf->b_ffname);
349 using_b_fname = (fname == curbuf->b_fname) || (sfname == curbuf->b_fname);
350#endif
351
Bram Moolenaardf177f62005-02-22 08:39:57 +0000352 /* After reading a file the cursor line changes but we don't want to
353 * display the line. */
354 ex_no_reprint = TRUE;
355
Bram Moolenaar55b7cf82006-09-09 12:52:42 +0000356 /* don't display the file info for another buffer now */
357 need_fileinfo = FALSE;
358
Bram Moolenaar071d4272004-06-13 20:20:40 +0000359 /*
360 * For Unix: Use the short file name whenever possible.
361 * Avoids problems with networks and when directory names are changed.
362 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
363 * another directory, which we don't detect.
364 */
365 if (sfname == NULL)
366 sfname = fname;
367#if defined(UNIX) || defined(__EMX__)
368 fname = sfname;
369#endif
370
371#ifdef FEAT_AUTOCMD
372 /*
373 * The BufReadCmd and FileReadCmd events intercept the reading process by
374 * executing the associated commands instead.
375 */
376 if (!filtering && !read_stdin && !read_buffer)
377 {
378 pos_T pos;
379
380 pos = curbuf->b_op_start;
381
382 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
383 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
384 curbuf->b_op_start.col = 0;
385
386 if (newfile)
387 {
388 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
389 FALSE, curbuf, eap))
390#ifdef FEAT_EVAL
391 return aborting() ? FAIL : OK;
392#else
393 return OK;
394#endif
395 }
396 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
397 FALSE, NULL, eap))
398#ifdef FEAT_EVAL
399 return aborting() ? FAIL : OK;
400#else
401 return OK;
402#endif
403
404 curbuf->b_op_start = pos;
405 }
406#endif
407
408 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
409 msg_scroll = FALSE; /* overwrite previous file message */
410 else
411 msg_scroll = TRUE; /* don't overwrite previous file message */
412
413 /*
414 * If the name ends in a path separator, we can't open it. Check here,
415 * because reading the file may actually work, but then creating the swap
416 * file may destroy it! Reported on MS-DOS and Win 95.
417 * If the name is too long we might crash further on, quit here.
418 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000419 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000421 p = fname + STRLEN(fname);
422 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000423 {
424 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
425 msg_end();
426 msg_scroll = msg_save;
427 return FAIL;
428 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000429 }
430
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431 if (!read_stdin && !read_buffer)
432 {
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200433#ifdef UNIX
434 /*
435 * On Unix it is possible to read a directory, so we have to
436 * check for it before the mch_open().
437 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000438 perm = mch_getperm(fname);
439 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
440# ifdef S_ISFIFO
441 && !S_ISFIFO(perm) /* ... or fifo */
442# endif
443# ifdef S_ISSOCK
444 && !S_ISSOCK(perm) /* ... or socket */
445# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +0000446# ifdef OPEN_CHR_FILES
447 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
448 /* ... or a character special file named /dev/fd/<n> */
449# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 )
451 {
452 if (S_ISDIR(perm))
453 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
454 else
455 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
456 msg_end();
457 msg_scroll = msg_save;
458 return FAIL;
459 }
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200460#endif
461#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000462 /*
463 * MS-Windows allows opening a device, but we will probably get stuck
464 * trying to read it.
465 */
466 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
467 {
Bram Moolenaar5386a122007-06-28 20:02:32 +0000468 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000469 msg_end();
470 msg_scroll = msg_save;
471 return FAIL;
472 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000473#endif
Bram Moolenaar4e4f5292013-08-30 17:07:01 +0200474 }
Bram Moolenaar043545e2006-10-10 16:44:07 +0000475
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200476 /* Set default or forced 'fileformat' and 'binary'. */
477 set_file_options(set_options, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000478
479 /*
480 * When opening a new file we take the readonly flag from the file.
481 * Default is r/w, can be set to r/o below.
482 * Don't reset it when in readonly mode
483 * Only set/reset b_p_ro when BF_CHECK_RO is set.
484 */
485 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000486 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487 curbuf->b_p_ro = FALSE;
488
489 if (newfile && !read_stdin && !read_buffer)
490 {
Bram Moolenaare60acc12011-05-10 16:41:25 +0200491 /* Remember time of file. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492 if (mch_stat((char *)fname, &st) >= 0)
493 {
494 buf_store_time(curbuf, &st, fname);
495 curbuf->b_mtime_read = curbuf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496#ifdef UNIX
497 /*
498 * Use the protection bits of the original file for the swap file.
499 * This makes it possible for others to read the name of the
500 * edited file from the swapfile, but only if they can read the
501 * edited file.
502 * Remove the "write" and "execute" bits for group and others
503 * (they must not write the swapfile).
504 * Add the "read" and "write" bits for the user, otherwise we may
505 * not be able to write to the file ourselves.
506 * Setting the bits is done below, after creating the swap file.
507 */
508 swap_mode = (st.st_mode & 0644) | 0600;
509#endif
510#ifdef FEAT_CW_EDITOR
511 /* Get the FSSpec on MacOS
512 * TODO: Update it properly when the buffer name changes
513 */
514 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
515#endif
516#ifdef VMS
517 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000518 curbuf->b_fab_rat = st.st_fab_rat;
519 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000520#endif
521 }
522 else
523 {
524 curbuf->b_mtime = 0;
525 curbuf->b_mtime_read = 0;
526 curbuf->b_orig_size = 0;
527 curbuf->b_orig_mode = 0;
528 }
529
530 /* Reset the "new file" flag. It will be set again below when the
531 * file doesn't exist. */
532 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
533 }
534
535/*
536 * for UNIX: check readonly with perm and mch_access()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537 * for MSDOS and Amiga: check readonly by trying to open the file for writing
538 */
539 file_readonly = FALSE;
540 if (read_stdin)
541 {
542#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
543 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
544 setmode(0, O_BINARY);
545#endif
546 }
547 else if (!read_buffer)
548 {
549#ifdef USE_MCH_ACCESS
550 if (
551# ifdef UNIX
552 !(perm & 0222) ||
553# endif
554 mch_access((char *)fname, W_OK))
555 file_readonly = TRUE;
556 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
557#else
558 if (!newfile
559 || readonlymode
560 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
561 {
562 file_readonly = TRUE;
563 /* try to open ro */
564 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
565 }
566#endif
567 }
568
569 if (fd < 0) /* cannot open at all */
570 {
571#ifndef UNIX
572 int isdir_f;
573#endif
574 msg_scroll = msg_save;
575#ifndef UNIX
576 /*
577 * On MSDOS and Amiga we can't open a directory, check here.
578 */
579 isdir_f = (mch_isdir(fname));
580 perm = mch_getperm(fname); /* check if the file exists */
581 if (isdir_f)
582 {
583 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
584 curbuf->b_p_ro = TRUE; /* must use "w!" now */
585 }
586 else
587#endif
588 if (newfile)
589 {
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200590 if (perm < 0
591#ifdef ENOENT
592 && errno == ENOENT
593#endif
594 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000595 {
596 /*
597 * Set the 'new-file' flag, so that when the file has
598 * been created by someone else, a ":w" will complain.
599 */
600 curbuf->b_flags |= BF_NEW;
601
602 /* Create a swap file now, so that other Vims are warned
603 * that we are editing this file. Don't do this for a
604 * "nofile" or "nowrite" buffer type. */
605#ifdef FEAT_QUICKFIX
606 if (!bt_dontwrite(curbuf))
607#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000608 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000610#ifdef FEAT_AUTOCMD
611 /* SwapExists autocommand may mess things up */
612 if (curbuf != old_curbuf
613 || (using_b_ffname
614 && (old_b_ffname != curbuf->b_ffname))
615 || (using_b_fname
616 && (old_b_fname != curbuf->b_fname)))
617 {
618 EMSG(_(e_auchangedbuf));
619 return FAIL;
620 }
621#endif
622 }
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000623 if (dir_of_file_exists(fname))
624 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
625 else
626 filemess(curbuf, sfname,
627 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628#ifdef FEAT_VIMINFO
629 /* Even though this is a new file, it might have been
630 * edited before and deleted. Get the old marks. */
631 check_marks_read();
632#endif
633#ifdef FEAT_MBYTE
Bram Moolenaarad875fb2013-07-24 15:02:03 +0200634 /* Set forced 'fileencoding'. */
635 if (eap != NULL)
636 set_forced_fenc(eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637#endif
638#ifdef FEAT_AUTOCMD
639 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
640 FALSE, curbuf, eap);
641#endif
642 /* remember the current fileformat */
643 save_file_ff(curbuf);
644
645#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
646 if (aborting()) /* autocmds may abort script processing */
647 return FAIL;
648#endif
649 return OK; /* a new file is not an error */
650 }
651 else
652 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000653 filemess(curbuf, sfname, (char_u *)(
654# ifdef EFBIG
655 (errno == EFBIG) ? _("[File too big]") :
656# endif
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200657# ifdef EOVERFLOW
658 (errno == EOVERFLOW) ? _("[File too big]") :
659# endif
Bram Moolenaar202795b2005-10-11 20:29:39 +0000660 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661 curbuf->b_p_ro = TRUE; /* must use "w!" now */
662 }
663 }
664
665 return FAIL;
666 }
667
668 /*
669 * Only set the 'ro' flag for readonly files the first time they are
670 * loaded. Help files always get readonly mode
671 */
672 if ((check_readonly && file_readonly) || curbuf->b_help)
673 curbuf->b_p_ro = TRUE;
674
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000675 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676 {
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000677 /* Don't change 'eol' if reading from buffer as it will already be
678 * correctly set when reading stdin. */
679 if (!read_buffer)
680 {
681 curbuf->b_p_eol = TRUE;
682 curbuf->b_start_eol = TRUE;
683 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684#ifdef FEAT_MBYTE
685 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000686 curbuf->b_start_bomb = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687#endif
688 }
689
690 /* Create a swap file now, so that other Vims are warned that we are
691 * editing this file.
692 * Don't do this for a "nofile" or "nowrite" buffer type. */
693#ifdef FEAT_QUICKFIX
694 if (!bt_dontwrite(curbuf))
695#endif
696 {
697 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000698#ifdef FEAT_AUTOCMD
699 if (!read_stdin && (curbuf != old_curbuf
700 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
701 || (using_b_fname && (old_b_fname != curbuf->b_fname))))
702 {
703 EMSG(_(e_auchangedbuf));
704 if (!read_buffer)
705 close(fd);
706 return FAIL;
707 }
708#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709#ifdef UNIX
710 /* Set swap file protection bits after creating it. */
Bram Moolenaarf061e0b2009-06-24 15:32:01 +0000711 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
712 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
714#endif
715 }
716
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000717#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 /* If "Quit" selected at ATTENTION dialog, don't load the file */
719 if (swap_exists_action == SEA_QUIT)
720 {
721 if (!read_buffer && !read_stdin)
722 close(fd);
723 return FAIL;
724 }
725#endif
726
727 ++no_wait_return; /* don't wait for return yet */
728
729 /*
730 * Set '[ mark to the line above where the lines go (line 1 if zero).
731 */
732 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
733 curbuf->b_op_start.col = 0;
734
735#ifdef FEAT_AUTOCMD
736 if (!read_buffer)
737 {
738 int m = msg_scroll;
739 int n = msg_scrolled;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740
741 /*
742 * The file must be closed again, the autocommands may want to change
743 * the file before reading it.
744 */
745 if (!read_stdin)
746 close(fd); /* ignore errors */
747
748 /*
749 * The output from the autocommands should not overwrite anything and
750 * should not be overwritten: Set msg_scroll, restore its value if no
751 * output was done.
752 */
753 msg_scroll = TRUE;
754 if (filtering)
755 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
756 FALSE, curbuf, eap);
757 else if (read_stdin)
758 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
759 FALSE, curbuf, eap);
760 else if (newfile)
761 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
762 FALSE, curbuf, eap);
763 else
764 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
765 FALSE, NULL, eap);
766 if (msg_scrolled == n)
767 msg_scroll = m;
768
769#ifdef FEAT_EVAL
770 if (aborting()) /* autocmds may abort script processing */
771 {
772 --no_wait_return;
773 msg_scroll = msg_save;
774 curbuf->b_p_ro = TRUE; /* must use "w!" now */
775 return FAIL;
776 }
777#endif
778 /*
779 * Don't allow the autocommands to change the current buffer.
780 * Try to re-open the file.
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000781 *
782 * Don't allow the autocommands to change the buffer name either
783 * (cd for example) if it invalidates fname or sfname.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784 */
785 if (!read_stdin && (curbuf != old_curbuf
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000786 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
787 || (using_b_fname && (old_b_fname != curbuf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
789 {
790 --no_wait_return;
791 msg_scroll = msg_save;
792 if (fd < 0)
793 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
794 else
795 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
796 curbuf->b_p_ro = TRUE; /* must use "w!" now */
797 return FAIL;
798 }
799 }
800#endif /* FEAT_AUTOCMD */
801
802 /* Autocommands may add lines to the file, need to check if it is empty */
803 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
804
805 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
806 {
807 /*
808 * Show the user that we are busy reading the input. Sometimes this
809 * may take a while. When reading from stdin another program may
810 * still be running, don't move the cursor to the last line, unless
811 * always using the GUI.
812 */
813 if (read_stdin)
814 {
815#ifndef ALWAYS_USE_GUI
816 mch_msg(_("Vim: Reading from stdin...\n"));
817#endif
818#ifdef FEAT_GUI
819 /* Also write a message in the GUI window, if there is one. */
820 if (gui.in_use && !gui.dying && !gui.starting)
821 {
822 p = (char_u *)_("Reading from stdin...");
823 gui_write(p, (int)STRLEN(p));
824 }
825#endif
826 }
827 else if (!read_buffer)
828 filemess(curbuf, sfname, (char_u *)"", 0);
829 }
830
831 msg_scroll = FALSE; /* overwrite the file message */
832
833 /*
834 * Set linecnt now, before the "retry" caused by a wrong guess for
835 * fileformat, and after the autocommands, which may change them.
836 */
837 linecnt = curbuf->b_ml.ml_line_count;
838
839#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000840 /* "++bad=" argument. */
841 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000842 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000843 bad_char_behavior = eap->bad_char;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000844 if (set_options)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000845 curbuf->b_bad_char = eap->bad_char;
846 }
847 else
848 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000849
Bram Moolenaar071d4272004-06-13 20:20:40 +0000850 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000851 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 */
853 if (eap != NULL && eap->force_enc != 0)
854 {
855 fenc = enc_canonize(eap->cmd + eap->force_enc);
856 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000857 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858 }
859 else if (curbuf->b_p_bin)
860 {
861 fenc = (char_u *)""; /* binary: don't convert */
862 fenc_alloced = FALSE;
863 }
864 else if (curbuf->b_help)
865 {
866 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000867 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868
869 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
870 * fails it must be latin1.
871 * Always do this when 'encoding' is "utf-8". Otherwise only do
872 * this when needed to avoid [converted] remarks all the time.
873 * It is needed when the first line contains non-ASCII characters.
874 * That is only in *.??x files. */
875 fenc = (char_u *)"latin1";
876 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000877 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000879 fc = fname[STRLEN(fname) - 1];
880 if (TOLOWER_ASC(fc) == 'x')
881 {
882 /* Read the first line (and a bit more). Immediately rewind to
883 * the start of the file. If the read() fails "len" is -1. */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +0100884 len = read_eintr(fd, firstline, 80);
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000885 lseek(fd, (off_t)0L, SEEK_SET);
886 for (p = firstline; p < firstline + len; ++p)
887 if (*p >= 0x80)
888 {
889 c = TRUE;
890 break;
891 }
892 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 }
894
895 if (c)
896 {
897 fenc_next = fenc;
898 fenc = (char_u *)"utf-8";
899
900 /* When the file is utf-8 but a character doesn't fit in
901 * 'encoding' don't retry. In help text editing utf-8 bytes
902 * doesn't make sense. */
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000903 if (!enc_utf8)
904 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905 }
906 fenc_alloced = FALSE;
907 }
908 else if (*p_fencs == NUL)
909 {
910 fenc = curbuf->b_p_fenc; /* use format from buffer */
911 fenc_alloced = FALSE;
912 }
913 else
914 {
915 fenc_next = p_fencs; /* try items in 'fileencodings' */
916 fenc = next_fenc(&fenc_next);
917 fenc_alloced = TRUE;
918 }
919#endif
920
921 /*
922 * Jump back here to retry reading the file in different ways.
923 * Reasons to retry:
924 * - encoding conversion failed: try another one from "fenc_next"
925 * - BOM detected and fenc was set, need to setup conversion
926 * - "fileformat" check failed: try another
927 *
928 * Variables set for special retry actions:
929 * "file_rewind" Rewind the file to start reading it again.
930 * "advance_fenc" Advance "fenc" using "fenc_next".
931 * "skip_read" Re-use already read bytes (BOM detected).
932 * "did_iconv" iconv() conversion failed, try 'charconvert'.
933 * "keep_fileformat" Don't reset "fileformat".
934 *
935 * Other status indicators:
936 * "tmpname" When != NULL did conversion with 'charconvert'.
937 * Output file has to be deleted afterwards.
938 * "iconv_fd" When != -1 did conversion with iconv().
939 */
940retry:
941
942 if (file_rewind)
943 {
944 if (read_buffer)
945 {
946 read_buf_lnum = 1;
947 read_buf_col = 0;
948 }
949 else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
950 {
951 /* Can't rewind the file, give up. */
952 error = TRUE;
953 goto failed;
954 }
955 /* Delete the previously read lines. */
956 while (lnum > from)
957 ml_delete(lnum--, FALSE);
958 file_rewind = FALSE;
959#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000960 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000961 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000962 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000963 curbuf->b_start_bomb = FALSE;
964 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000965 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966#endif
967 }
968
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +0200969#ifdef FEAT_CRYPT
970 if (cryptkey != NULL)
971 /* Need to reset the state, but keep the key, don't want to ask for it
972 * again. */
973 crypt_pop_state();
974#endif
975
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976 /*
977 * When retrying with another "fenc" and the first time "fileformat"
978 * will be reset.
979 */
980 if (keep_fileformat)
981 keep_fileformat = FALSE;
982 else
983 {
984 if (eap != NULL && eap->force_ff != 0)
Bram Moolenaar1c860362008-11-12 15:05:21 +0000985 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 fileformat = get_fileformat_force(curbuf, eap);
Bram Moolenaar1c860362008-11-12 15:05:21 +0000987 try_unix = try_dos = try_mac = FALSE;
988 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 else if (curbuf->b_p_bin)
990 fileformat = EOL_UNIX; /* binary: use Unix format */
991 else if (*p_ffs == NUL)
992 fileformat = get_fileformat(curbuf);/* use format from buffer */
993 else
994 fileformat = EOL_UNKNOWN; /* detect from file */
995 }
996
997#ifdef FEAT_MBYTE
998# ifdef USE_ICONV
999 if (iconv_fd != (iconv_t)-1)
1000 {
1001 /* aborted conversion with iconv(), close the descriptor */
1002 iconv_close(iconv_fd);
1003 iconv_fd = (iconv_t)-1;
1004 }
1005# endif
1006
1007 if (advance_fenc)
1008 {
1009 /*
1010 * Try the next entry in 'fileencodings'.
1011 */
1012 advance_fenc = FALSE;
1013
1014 if (eap != NULL && eap->force_enc != 0)
1015 {
1016 /* Conversion given with "++cc=" wasn't possible, read
1017 * without conversion. */
1018 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001019 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020 if (fenc_alloced)
1021 vim_free(fenc);
1022 fenc = (char_u *)"";
1023 fenc_alloced = FALSE;
1024 }
1025 else
1026 {
1027 if (fenc_alloced)
1028 vim_free(fenc);
1029 if (fenc_next != NULL)
1030 {
1031 fenc = next_fenc(&fenc_next);
1032 fenc_alloced = (fenc_next != NULL);
1033 }
1034 else
1035 {
1036 fenc = (char_u *)"";
1037 fenc_alloced = FALSE;
1038 }
1039 }
1040 if (tmpname != NULL)
1041 {
1042 mch_remove(tmpname); /* delete converted file */
1043 vim_free(tmpname);
1044 tmpname = NULL;
1045 }
1046 }
1047
1048 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001049 * Conversion may be required when the encoding of the file is different
1050 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 */
1052 fio_flags = 0;
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001053 converted = need_conversion(fenc);
1054 if (converted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001055 {
1056
1057 /* "ucs-bom" means we need to check the first bytes of the file
1058 * for a BOM. */
1059 if (STRCMP(fenc, ENC_UCSBOM) == 0)
1060 fio_flags = FIO_UCSBOM;
1061
1062 /*
1063 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
1064 * done. This is handled below after read(). Prepare the
1065 * fio_flags to avoid having to parse the string each time.
1066 * Also check for Unicode to Latin1 conversion, because iconv()
1067 * appears not to handle this correctly. This works just like
1068 * conversion to UTF-8 except how the resulting character is put in
1069 * the buffer.
1070 */
1071 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
1072 fio_flags = get_fio_flags(fenc);
1073
1074# ifdef WIN3264
1075 /*
1076 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
1077 * is handled with MultiByteToWideChar().
1078 */
1079 if (fio_flags == 0)
1080 fio_flags = get_win_fio_flags(fenc);
1081# endif
1082
1083# ifdef MACOS_X
1084 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
1085 if (fio_flags == 0)
1086 fio_flags = get_mac_fio_flags(fenc);
1087# endif
1088
1089# ifdef USE_ICONV
1090 /*
1091 * Try using iconv() if we can't convert internally.
1092 */
1093 if (fio_flags == 0
1094# ifdef FEAT_EVAL
1095 && !did_iconv
1096# endif
1097 )
1098 iconv_fd = (iconv_t)my_iconv_open(
1099 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
1100# endif
1101
1102# ifdef FEAT_EVAL
1103 /*
1104 * Use the 'charconvert' expression when conversion is required
1105 * and we can't do it internally or with iconv().
1106 */
1107 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1108# ifdef USE_ICONV
1109 && iconv_fd == (iconv_t)-1
1110# endif
1111 )
1112 {
1113# ifdef USE_ICONV
1114 did_iconv = FALSE;
1115# endif
1116 /* Skip conversion when it's already done (retry for wrong
1117 * "fileformat"). */
1118 if (tmpname == NULL)
1119 {
1120 tmpname = readfile_charconvert(fname, fenc, &fd);
1121 if (tmpname == NULL)
1122 {
1123 /* Conversion failed. Try another one. */
1124 advance_fenc = TRUE;
1125 if (fd < 0)
1126 {
1127 /* Re-opening the original file failed! */
1128 EMSG(_("E202: Conversion made file unreadable!"));
1129 error = TRUE;
1130 goto failed;
1131 }
1132 goto retry;
1133 }
1134 }
1135 }
1136 else
1137# endif
1138 {
1139 if (fio_flags == 0
1140# ifdef USE_ICONV
1141 && iconv_fd == (iconv_t)-1
1142# endif
1143 )
1144 {
1145 /* Conversion wanted but we can't.
1146 * Try the next conversion in 'fileencodings' */
1147 advance_fenc = TRUE;
1148 goto retry;
1149 }
1150 }
1151 }
1152
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001153 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001154 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001155 * stdin or fixed at a specific encoding. */
1156 can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001157#endif
1158
1159 if (!skip_read)
1160 {
1161 linerest = 0;
1162 filesize = 0;
1163 skip_count = lines_to_skip;
1164 read_count = lines_to_read;
1165#ifdef FEAT_MBYTE
1166 conv_restlen = 0;
1167#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001168#ifdef FEAT_PERSISTENT_UNDO
Bram Moolenaar59f931e2010-07-24 20:27:03 +02001169 read_undo_file = (newfile && (flags & READ_KEEP_UNDO) == 0
1170 && curbuf->b_ffname != NULL
1171 && curbuf->b_p_udf
1172 && !filtering
1173 && !read_stdin
1174 && !read_buffer);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02001175 if (read_undo_file)
1176 sha256_start(&sha_ctx);
1177#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001178 }
1179
1180 while (!error && !got_int)
1181 {
1182 /*
1183 * We allocate as much space for the file as we can get, plus
1184 * space for the old line plus room for one terminating NUL.
1185 * The amount is limited by the fact that read() only can read
1186 * upto max_unsigned characters (and other things).
1187 */
Bram Moolenaara2aa31a2014-02-23 22:52:40 +01001188#if VIM_SIZEOF_INT <= 2
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189 if (linerest >= 0x7ff0)
1190 {
1191 ++split;
1192 *ptr = NL; /* split line by inserting a NL */
1193 size = 1;
1194 }
1195 else
1196#endif
1197 {
1198 if (!skip_read)
1199 {
Bram Moolenaara2aa31a2014-02-23 22:52:40 +01001200#if VIM_SIZEOF_INT > 2
Bram Moolenaar311d9822007-02-27 15:48:28 +00001201# if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202 size = SSIZE_MAX; /* use max I/O size, 52K */
1203# else
1204 size = 0x10000L; /* use buffer >= 64K */
1205# endif
1206#else
1207 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1208#endif
1209
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001210 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001211 {
1212 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1213 FALSE)) != NULL)
1214 break;
1215 }
1216 if (new_buffer == NULL)
1217 {
1218 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1219 error = TRUE;
1220 break;
1221 }
1222 if (linerest) /* copy characters from the previous buffer */
1223 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1224 vim_free(buffer);
1225 buffer = new_buffer;
1226 ptr = buffer + linerest;
1227 line_start = buffer;
1228
1229#ifdef FEAT_MBYTE
1230 /* May need room to translate into.
1231 * For iconv() we don't really know the required space, use a
1232 * factor ICONV_MULT.
1233 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1234 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1235 * become up to 4 bytes, size must be multiple of 2
1236 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1237 * multiple of 2
1238 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1239 * multiple of 4 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001240 real_size = (int)size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241# ifdef USE_ICONV
1242 if (iconv_fd != (iconv_t)-1)
1243 size = size / ICONV_MULT;
1244 else
1245# endif
1246 if (fio_flags & FIO_LATIN1)
1247 size = size / 2;
1248 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1249 size = (size * 2 / 3) & ~1;
1250 else if (fio_flags & FIO_UCS4)
1251 size = (size * 2 / 3) & ~3;
1252 else if (fio_flags == FIO_UCSBOM)
1253 size = size / ICONV_MULT; /* worst case */
1254# ifdef WIN3264
1255 else if (fio_flags & FIO_CODEPAGE)
1256 size = size / ICONV_MULT; /* also worst case */
1257# endif
1258# ifdef MACOS_X
1259 else if (fio_flags & FIO_MACROMAN)
1260 size = size / ICONV_MULT; /* also worst case */
1261# endif
1262#endif
1263
1264#ifdef FEAT_MBYTE
1265 if (conv_restlen > 0)
1266 {
1267 /* Insert unconverted bytes from previous line. */
1268 mch_memmove(ptr, conv_rest, conv_restlen);
1269 ptr += conv_restlen;
1270 size -= conv_restlen;
1271 }
1272#endif
1273
1274 if (read_buffer)
1275 {
1276 /*
1277 * Read bytes from curbuf. Used for converting text read
1278 * from stdin.
1279 */
1280 if (read_buf_lnum > from)
1281 size = 0;
1282 else
1283 {
1284 int n, ni;
1285 long tlen;
1286
1287 tlen = 0;
1288 for (;;)
1289 {
1290 p = ml_get(read_buf_lnum) + read_buf_col;
1291 n = (int)STRLEN(p);
1292 if ((int)tlen + n + 1 > size)
1293 {
1294 /* Filled up to "size", append partial line.
1295 * Change NL to NUL to reverse the effect done
1296 * below. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001297 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298 for (ni = 0; ni < n; ++ni)
1299 {
1300 if (p[ni] == NL)
1301 ptr[tlen++] = NUL;
1302 else
1303 ptr[tlen++] = p[ni];
1304 }
1305 read_buf_col += n;
1306 break;
1307 }
1308 else
1309 {
1310 /* Append whole line and new-line. Change NL
1311 * to NUL to reverse the effect done below. */
1312 for (ni = 0; ni < n; ++ni)
1313 {
1314 if (p[ni] == NL)
1315 ptr[tlen++] = NUL;
1316 else
1317 ptr[tlen++] = p[ni];
1318 }
1319 ptr[tlen++] = NL;
1320 read_buf_col = 0;
1321 if (++read_buf_lnum > from)
1322 {
1323 /* When the last line didn't have an
1324 * end-of-line don't add it now either. */
1325 if (!curbuf->b_p_eol)
1326 --tlen;
1327 size = tlen;
1328 break;
1329 }
1330 }
1331 }
1332 }
1333 }
1334 else
1335 {
1336 /*
1337 * Read bytes from the file.
1338 */
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01001339 size = read_eintr(fd, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001340 }
1341
1342 if (size <= 0)
1343 {
1344 if (size < 0) /* read error */
1345 error = TRUE;
1346#ifdef FEAT_MBYTE
1347 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001348 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001349 /*
1350 * Reached end-of-file but some trailing bytes could
1351 * not be converted. Truncated file?
1352 */
1353
1354 /* When we did a conversion report an error. */
1355 if (fio_flags != 0
1356# ifdef USE_ICONV
1357 || iconv_fd != (iconv_t)-1
1358# endif
1359 )
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001360 {
Bram Moolenaare8d95302013-04-24 16:34:02 +02001361 if (can_retry)
1362 goto rewind_retry;
Bram Moolenaarf453d352008-06-04 17:37:34 +00001363 if (conv_error == 0)
1364 conv_error = curbuf->b_ml.ml_line_count
1365 - linecnt + 1;
1366 }
1367 /* Remember the first linenr with an illegal byte */
1368 else if (illegal_byte == 0)
1369 illegal_byte = curbuf->b_ml.ml_line_count
1370 - linecnt + 1;
1371 if (bad_char_behavior == BAD_DROP)
1372 {
1373 *(ptr - conv_restlen) = NUL;
1374 conv_restlen = 0;
1375 }
1376 else
1377 {
1378 /* Replace the trailing bytes with the replacement
1379 * character if we were converting; if we weren't,
1380 * leave the UTF8 checking code to do it, as it
1381 * works slightly differently. */
1382 if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
1383# ifdef USE_ICONV
1384 || iconv_fd != (iconv_t)-1
1385# endif
1386 ))
1387 {
1388 while (conv_restlen > 0)
1389 {
1390 *(--ptr) = bad_char_behavior;
1391 --conv_restlen;
1392 }
1393 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001394 fio_flags = 0; /* don't convert this */
Bram Moolenaarb21e5842006-04-16 18:30:08 +00001395# ifdef USE_ICONV
1396 if (iconv_fd != (iconv_t)-1)
1397 {
1398 iconv_close(iconv_fd);
1399 iconv_fd = (iconv_t)-1;
1400 }
1401# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001402 }
1403 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001404#endif
1405 }
1406
1407#ifdef FEAT_CRYPT
1408 /*
1409 * At start of file: Check for magic number of encryption.
1410 */
1411 if (filesize == 0)
1412 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02001413 &filesize, newfile, sfname,
1414 &did_ask_for_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001415 /*
1416 * Decrypt the read bytes.
1417 */
1418 if (cryptkey != NULL && size > 0)
Bram Moolenaar04c9baf2010-06-01 23:37:39 +02001419 crypt_decode(ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001420#endif
1421 }
1422 skip_read = FALSE;
1423
1424#ifdef FEAT_MBYTE
1425 /*
1426 * At start of file (or after crypt magic number): Check for BOM.
1427 * Also check for a BOM for other Unicode encodings, but not after
1428 * converting with 'charconvert' or when a BOM has already been
1429 * found.
1430 */
1431 if ((filesize == 0
1432# ifdef FEAT_CRYPT
Bram Moolenaar40e6a712010-05-16 22:32:54 +02001433 || (filesize == (CRYPT_MAGIC_LEN
Bram Moolenaar80794b12010-06-13 05:20:42 +02001434 + crypt_salt_len[use_crypt_method]
Bram Moolenaar40e6a712010-05-16 22:32:54 +02001435 + crypt_seed_len[use_crypt_method])
1436 && cryptkey != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001437# endif
1438 )
1439 && (fio_flags == FIO_UCSBOM
1440 || (!curbuf->b_p_bomb
1441 && tmpname == NULL
1442 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1443 {
1444 char_u *ccname;
1445 int blen;
1446
1447 /* no BOM detection in a short file or in binary mode */
1448 if (size < 2 || curbuf->b_p_bin)
1449 ccname = NULL;
1450 else
1451 ccname = check_for_bom(ptr, size, &blen,
1452 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1453 if (ccname != NULL)
1454 {
1455 /* Remove BOM from the text */
1456 filesize += blen;
1457 size -= blen;
1458 mch_memmove(ptr, ptr + blen, (size_t)size);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001459 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001460 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001461 curbuf->b_p_bomb = TRUE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00001462 curbuf->b_start_bomb = TRUE;
1463 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001464 }
1465
1466 if (fio_flags == FIO_UCSBOM)
1467 {
1468 if (ccname == NULL)
1469 {
1470 /* No BOM detected: retry with next encoding. */
1471 advance_fenc = TRUE;
1472 }
1473 else
1474 {
1475 /* BOM detected: set "fenc" and jump back */
1476 if (fenc_alloced)
1477 vim_free(fenc);
1478 fenc = ccname;
1479 fenc_alloced = FALSE;
1480 }
1481 /* retry reading without getting new bytes or rewinding */
1482 skip_read = TRUE;
1483 goto retry;
1484 }
1485 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00001486
1487 /* Include not converted bytes. */
1488 ptr -= conv_restlen;
1489 size += conv_restlen;
1490 conv_restlen = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491#endif
1492 /*
1493 * Break here for a read error or end-of-file.
1494 */
1495 if (size <= 0)
1496 break;
1497
1498#ifdef FEAT_MBYTE
1499
Bram Moolenaar071d4272004-06-13 20:20:40 +00001500# ifdef USE_ICONV
1501 if (iconv_fd != (iconv_t)-1)
1502 {
1503 /*
1504 * Attempt conversion of the read bytes to 'encoding' using
1505 * iconv().
1506 */
1507 const char *fromp;
1508 char *top;
1509 size_t from_size;
1510 size_t to_size;
1511
1512 fromp = (char *)ptr;
1513 from_size = size;
1514 ptr += size;
1515 top = (char *)ptr;
1516 to_size = real_size - size;
1517
1518 /*
1519 * If there is conversion error or not enough room try using
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001520 * another conversion. Except for when there is no
1521 * alternative (help files).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001522 */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001523 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1524 &top, &to_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1526 || from_size > CONV_RESTLEN)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001527 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001528 if (can_retry)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001529 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001530 if (conv_error == 0)
1531 conv_error = readfile_linenr(linecnt,
1532 ptr, (char_u *)top);
Bram Moolenaar42eeac32005-06-29 22:40:58 +00001533
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001534 /* Deal with a bad byte and continue with the next. */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001535 ++fromp;
1536 --from_size;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001537 if (bad_char_behavior == BAD_KEEP)
1538 {
1539 *top++ = *(fromp - 1);
1540 --to_size;
1541 }
1542 else if (bad_char_behavior != BAD_DROP)
1543 {
1544 *top++ = bad_char_behavior;
1545 --to_size;
1546 }
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001547 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001548
1549 if (from_size > 0)
1550 {
1551 /* Some remaining characters, keep them for the next
1552 * round. */
1553 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1554 conv_restlen = (int)from_size;
1555 }
1556
1557 /* move the linerest to before the converted characters */
1558 line_start = ptr - linerest;
1559 mch_memmove(line_start, buffer, (size_t)linerest);
1560 size = (long)((char_u *)top - ptr);
1561 }
1562# endif
1563
1564# ifdef WIN3264
1565 if (fio_flags & FIO_CODEPAGE)
1566 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001567 char_u *src, *dst;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001568 WCHAR ucs2buf[3];
1569 int ucs2len;
1570 int codepage = FIO_GET_CP(fio_flags);
1571 int bytelen;
1572 int found_bad;
1573 char replstr[2];
1574
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575 /*
1576 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001577 * a codepage, using standard MS-Windows functions. This
1578 * requires two steps:
1579 * 1. convert from 'fileencoding' to ucs-2
1580 * 2. convert from ucs-2 to 'encoding'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001581 *
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001582 * Because there may be illegal bytes AND an incomplete byte
1583 * sequence at the end, we may have to do the conversion one
1584 * character at a time to get it right.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001585 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001586
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001587 /* Replacement string for WideCharToMultiByte(). */
1588 if (bad_char_behavior > 0)
1589 replstr[0] = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001590 else
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001591 replstr[0] = '?';
1592 replstr[1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593
1594 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001595 * Move the bytes to the end of the buffer, so that we have
1596 * room to put the result at the start.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001597 */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001598 src = ptr + real_size - size;
1599 mch_memmove(src, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001600
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001601 /*
1602 * Do the conversion.
1603 */
1604 dst = ptr;
1605 size = size;
1606 while (size > 0)
1607 {
1608 found_bad = FALSE;
1609
1610# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1611 if (codepage == CP_UTF8)
1612 {
1613 /* Handle CP_UTF8 input ourselves to be able to handle
1614 * trailing bytes properly.
1615 * Get one UTF-8 character from src. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001616 bytelen = (int)utf_ptr2len_len(src, size);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001617 if (bytelen > size)
1618 {
1619 /* Only got some bytes of a character. Normally
1620 * it's put in "conv_rest", but if it's too long
1621 * deal with it as if they were illegal bytes. */
1622 if (bytelen <= CONV_RESTLEN)
1623 break;
1624
1625 /* weird overlong byte sequence */
1626 bytelen = size;
1627 found_bad = TRUE;
1628 }
1629 else
1630 {
Bram Moolenaarc01140a2006-03-24 22:21:52 +00001631 int u8c = utf_ptr2char(src);
1632
Bram Moolenaar86e01082005-12-29 22:45:34 +00001633 if (u8c > 0xffff || (*src >= 0x80 && bytelen == 1))
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001634 found_bad = TRUE;
1635 ucs2buf[0] = u8c;
1636 ucs2len = 1;
1637 }
1638 }
1639 else
1640# endif
1641 {
1642 /* We don't know how long the byte sequence is, try
1643 * from one to three bytes. */
1644 for (bytelen = 1; bytelen <= size && bytelen <= 3;
1645 ++bytelen)
1646 {
1647 ucs2len = MultiByteToWideChar(codepage,
1648 MB_ERR_INVALID_CHARS,
1649 (LPCSTR)src, bytelen,
1650 ucs2buf, 3);
1651 if (ucs2len > 0)
1652 break;
1653 }
1654 if (ucs2len == 0)
1655 {
1656 /* If we have only one byte then it's probably an
1657 * incomplete byte sequence. Otherwise discard
1658 * one byte as a bad character. */
1659 if (size == 1)
1660 break;
1661 found_bad = TRUE;
1662 bytelen = 1;
1663 }
1664 }
1665
1666 if (!found_bad)
1667 {
1668 int i;
1669
1670 /* Convert "ucs2buf[ucs2len]" to 'enc' in "dst". */
1671 if (enc_utf8)
1672 {
1673 /* From UCS-2 to UTF-8. Cannot fail. */
1674 for (i = 0; i < ucs2len; ++i)
1675 dst += utf_char2bytes(ucs2buf[i], dst);
1676 }
1677 else
1678 {
1679 BOOL bad = FALSE;
1680 int dstlen;
1681
1682 /* From UCS-2 to "enc_codepage". If the
1683 * conversion uses the default character "?",
1684 * the data doesn't fit in this encoding. */
1685 dstlen = WideCharToMultiByte(enc_codepage, 0,
1686 (LPCWSTR)ucs2buf, ucs2len,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001687 (LPSTR)dst, (int)(src - dst),
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001688 replstr, &bad);
1689 if (bad)
1690 found_bad = TRUE;
1691 else
1692 dst += dstlen;
1693 }
1694 }
1695
1696 if (found_bad)
1697 {
1698 /* Deal with bytes we can't convert. */
1699 if (can_retry)
1700 goto rewind_retry;
1701 if (conv_error == 0)
1702 conv_error = readfile_linenr(linecnt, ptr, dst);
1703 if (bad_char_behavior != BAD_DROP)
1704 {
1705 if (bad_char_behavior == BAD_KEEP)
1706 {
1707 mch_memmove(dst, src, bytelen);
1708 dst += bytelen;
1709 }
1710 else
1711 *dst++ = bad_char_behavior;
1712 }
1713 }
1714
1715 src += bytelen;
1716 size -= bytelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001717 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001718
1719 if (size > 0)
1720 {
1721 /* An incomplete byte sequence remaining. */
1722 mch_memmove(conv_rest, src, size);
1723 conv_restlen = size;
1724 }
1725
1726 /* The new size is equal to how much "dst" was advanced. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001727 size = (long)(dst - ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001728 }
1729 else
1730# endif
Bram Moolenaar56718732006-03-15 22:53:57 +00001731# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001732 if (fio_flags & FIO_MACROMAN)
1733 {
1734 /*
1735 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001736 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001738 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001739 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001740 }
1741 else
1742# endif
1743 if (fio_flags != 0)
1744 {
1745 int u8c;
1746 char_u *dest;
1747 char_u *tail = NULL;
1748
1749 /*
1750 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1751 * "enc_utf8" not set: Convert Unicode to Latin1.
1752 * Go from end to start through the buffer, because the number
1753 * of bytes may increase.
1754 * "dest" points to after where the UTF-8 bytes go, "p" points
1755 * to after the next character to convert.
1756 */
1757 dest = ptr + real_size;
1758 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1759 {
1760 p = ptr + size;
1761 if (fio_flags == FIO_UTF8)
1762 {
1763 /* Check for a trailing incomplete UTF-8 sequence */
1764 tail = ptr + size - 1;
1765 while (tail > ptr && (*tail & 0xc0) == 0x80)
1766 --tail;
1767 if (tail + utf_byte2len(*tail) <= ptr + size)
1768 tail = NULL;
1769 else
1770 p = tail;
1771 }
1772 }
1773 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1774 {
1775 /* Check for a trailing byte */
1776 p = ptr + (size & ~1);
1777 if (size & 1)
1778 tail = p;
1779 if ((fio_flags & FIO_UTF16) && p > ptr)
1780 {
1781 /* Check for a trailing leading word */
1782 if (fio_flags & FIO_ENDIAN_L)
1783 {
1784 u8c = (*--p << 8);
1785 u8c += *--p;
1786 }
1787 else
1788 {
1789 u8c = *--p;
1790 u8c += (*--p << 8);
1791 }
1792 if (u8c >= 0xd800 && u8c <= 0xdbff)
1793 tail = p;
1794 else
1795 p += 2;
1796 }
1797 }
1798 else /* FIO_UCS4 */
1799 {
1800 /* Check for trailing 1, 2 or 3 bytes */
1801 p = ptr + (size & ~3);
1802 if (size & 3)
1803 tail = p;
1804 }
1805
1806 /* If there is a trailing incomplete sequence move it to
1807 * conv_rest[]. */
1808 if (tail != NULL)
1809 {
1810 conv_restlen = (int)((ptr + size) - tail);
1811 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1812 size -= conv_restlen;
1813 }
1814
1815
1816 while (p > ptr)
1817 {
1818 if (fio_flags & FIO_LATIN1)
1819 u8c = *--p;
1820 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1821 {
1822 if (fio_flags & FIO_ENDIAN_L)
1823 {
1824 u8c = (*--p << 8);
1825 u8c += *--p;
1826 }
1827 else
1828 {
1829 u8c = *--p;
1830 u8c += (*--p << 8);
1831 }
1832 if ((fio_flags & FIO_UTF16)
1833 && u8c >= 0xdc00 && u8c <= 0xdfff)
1834 {
1835 int u16c;
1836
1837 if (p == ptr)
1838 {
1839 /* Missing leading word. */
1840 if (can_retry)
1841 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001842 if (conv_error == 0)
1843 conv_error = readfile_linenr(linecnt,
1844 ptr, p);
1845 if (bad_char_behavior == BAD_DROP)
1846 continue;
1847 if (bad_char_behavior != BAD_KEEP)
1848 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001849 }
1850
1851 /* found second word of double-word, get the first
1852 * word and compute the resulting character */
1853 if (fio_flags & FIO_ENDIAN_L)
1854 {
1855 u16c = (*--p << 8);
1856 u16c += *--p;
1857 }
1858 else
1859 {
1860 u16c = *--p;
1861 u16c += (*--p << 8);
1862 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001863 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1864 + (u8c & 0x3ff);
1865
Bram Moolenaar071d4272004-06-13 20:20:40 +00001866 /* Check if the word is indeed a leading word. */
1867 if (u16c < 0xd800 || u16c > 0xdbff)
1868 {
1869 if (can_retry)
1870 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001871 if (conv_error == 0)
1872 conv_error = readfile_linenr(linecnt,
1873 ptr, p);
1874 if (bad_char_behavior == BAD_DROP)
1875 continue;
1876 if (bad_char_behavior != BAD_KEEP)
1877 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001878 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001879 }
1880 }
1881 else if (fio_flags & FIO_UCS4)
1882 {
1883 if (fio_flags & FIO_ENDIAN_L)
1884 {
1885 u8c = (*--p << 24);
1886 u8c += (*--p << 16);
1887 u8c += (*--p << 8);
1888 u8c += *--p;
1889 }
1890 else /* big endian */
1891 {
1892 u8c = *--p;
1893 u8c += (*--p << 8);
1894 u8c += (*--p << 16);
1895 u8c += (*--p << 24);
1896 }
1897 }
1898 else /* UTF-8 */
1899 {
1900 if (*--p < 0x80)
1901 u8c = *p;
1902 else
1903 {
1904 len = utf_head_off(ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001905 p -= len;
1906 u8c = utf_ptr2char(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001907 if (len == 0)
1908 {
1909 /* Not a valid UTF-8 character, retry with
1910 * another fenc when possible, otherwise just
1911 * report the error. */
1912 if (can_retry)
1913 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001914 if (conv_error == 0)
1915 conv_error = readfile_linenr(linecnt,
1916 ptr, p);
1917 if (bad_char_behavior == BAD_DROP)
1918 continue;
1919 if (bad_char_behavior != BAD_KEEP)
1920 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001921 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001922 }
1923 }
1924 if (enc_utf8) /* produce UTF-8 */
1925 {
1926 dest -= utf_char2len(u8c);
1927 (void)utf_char2bytes(u8c, dest);
1928 }
1929 else /* produce Latin1 */
1930 {
1931 --dest;
1932 if (u8c >= 0x100)
1933 {
1934 /* character doesn't fit in latin1, retry with
1935 * another fenc when possible, otherwise just
1936 * report the error. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001937 if (can_retry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001938 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001939 if (conv_error == 0)
1940 conv_error = readfile_linenr(linecnt, ptr, p);
1941 if (bad_char_behavior == BAD_DROP)
1942 ++dest;
1943 else if (bad_char_behavior == BAD_KEEP)
1944 *dest = u8c;
1945 else if (eap != NULL && eap->bad_char != 0)
1946 *dest = bad_char_behavior;
1947 else
1948 *dest = 0xBF;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001949 }
1950 else
1951 *dest = u8c;
1952 }
1953 }
1954
1955 /* move the linerest to before the converted characters */
1956 line_start = dest - linerest;
1957 mch_memmove(line_start, buffer, (size_t)linerest);
1958 size = (long)((ptr + real_size) - dest);
1959 ptr = dest;
1960 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00001961 else if (enc_utf8 && !curbuf->b_p_bin)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001962 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001963 int incomplete_tail = FALSE;
1964
1965 /* Reading UTF-8: Check if the bytes are valid UTF-8. */
1966 for (p = ptr; ; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001967 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001968 int todo = (int)((ptr + size) - p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001969 int l;
1970
1971 if (todo <= 0)
1972 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001973 if (*p >= 0x80)
1974 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001975 /* A length of 1 means it's an illegal byte. Accept
1976 * an incomplete character at the end though, the next
1977 * read() will get the next bytes, we'll check it
1978 * then. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001979 l = utf_ptr2len_len(p, todo);
Bram Moolenaarf453d352008-06-04 17:37:34 +00001980 if (l > todo && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001981 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001982 /* Avoid retrying with a different encoding when
1983 * a truncated file is more likely, or attempting
1984 * to read the rest of an incomplete sequence when
1985 * we have already done so. */
1986 if (p > ptr || filesize > 0)
1987 incomplete_tail = TRUE;
1988 /* Incomplete byte sequence, move it to conv_rest[]
1989 * and try to read the rest of it, unless we've
1990 * already done so. */
1991 if (p > ptr)
1992 {
1993 conv_restlen = todo;
1994 mch_memmove(conv_rest, p, conv_restlen);
1995 size -= conv_restlen;
1996 break;
1997 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001998 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00001999 if (l == 1 || l > todo)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002000 {
2001 /* Illegal byte. If we can try another encoding
Bram Moolenaarf453d352008-06-04 17:37:34 +00002002 * do that, unless at EOF where a truncated
2003 * file is more likely than a conversion error. */
2004 if (can_retry && !incomplete_tail)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002005 break;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002006# ifdef USE_ICONV
2007 /* When we did a conversion report an error. */
2008 if (iconv_fd != (iconv_t)-1 && conv_error == 0)
2009 conv_error = readfile_linenr(linecnt, ptr, p);
2010# endif
Bram Moolenaarf453d352008-06-04 17:37:34 +00002011 /* Remember the first linenr with an illegal byte */
2012 if (conv_error == 0 && illegal_byte == 0)
2013 illegal_byte = readfile_linenr(linecnt, ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002014
2015 /* Drop, keep or replace the bad byte. */
2016 if (bad_char_behavior == BAD_DROP)
2017 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00002018 mch_memmove(p, p + 1, todo - 1);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002019 --p;
2020 --size;
2021 }
2022 else if (bad_char_behavior != BAD_KEEP)
2023 *p = bad_char_behavior;
2024 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002025 else
2026 p += l - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002027 }
2028 }
Bram Moolenaarf453d352008-06-04 17:37:34 +00002029 if (p < ptr + size && !incomplete_tail)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030 {
2031 /* Detected a UTF-8 error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002032rewind_retry:
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002033 /* Retry reading with another conversion. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002034# if defined(FEAT_EVAL) && defined(USE_ICONV)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002035 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
2036 /* iconv() failed, try 'charconvert' */
2037 did_iconv = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002038 else
2039# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002040 /* use next item from 'fileencodings' */
2041 advance_fenc = TRUE;
2042 file_rewind = TRUE;
2043 goto retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002044 }
2045 }
2046#endif
2047
2048 /* count the number of characters (after conversion!) */
2049 filesize += size;
2050
2051 /*
2052 * when reading the first part of a file: guess EOL type
2053 */
2054 if (fileformat == EOL_UNKNOWN)
2055 {
2056 /* First try finding a NL, for Dos and Unix */
2057 if (try_dos || try_unix)
2058 {
2059 for (p = ptr; p < ptr + size; ++p)
2060 {
2061 if (*p == NL)
2062 {
2063 if (!try_unix
2064 || (try_dos && p > ptr && p[-1] == CAR))
2065 fileformat = EOL_DOS;
2066 else
2067 fileformat = EOL_UNIX;
2068 break;
2069 }
2070 }
2071
2072 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
2073 if (fileformat == EOL_UNIX && try_mac)
2074 {
2075 /* Need to reset the counters when retrying fenc. */
2076 try_mac = 1;
2077 try_unix = 1;
2078 for (; p >= ptr && *p != CAR; p--)
2079 ;
2080 if (p >= ptr)
2081 {
2082 for (p = ptr; p < ptr + size; ++p)
2083 {
2084 if (*p == NL)
2085 try_unix++;
2086 else if (*p == CAR)
2087 try_mac++;
2088 }
2089 if (try_mac > try_unix)
2090 fileformat = EOL_MAC;
2091 }
2092 }
2093 }
2094
2095 /* No NL found: may use Mac format */
2096 if (fileformat == EOL_UNKNOWN && try_mac)
2097 fileformat = EOL_MAC;
2098
2099 /* Still nothing found? Use first format in 'ffs' */
2100 if (fileformat == EOL_UNKNOWN)
2101 fileformat = default_fileformat();
2102
2103 /* if editing a new file: may set p_tx and p_ff */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002104 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002105 set_fileformat(fileformat, OPT_LOCAL);
2106 }
2107 }
2108
2109 /*
2110 * This loop is executed once for every character read.
2111 * Keep it fast!
2112 */
2113 if (fileformat == EOL_MAC)
2114 {
2115 --ptr;
2116 while (++ptr, --size >= 0)
2117 {
2118 /* catch most common case first */
2119 if ((c = *ptr) != NUL && c != CAR && c != NL)
2120 continue;
2121 if (c == NUL)
2122 *ptr = NL; /* NULs are replaced by newlines! */
2123 else if (c == NL)
2124 *ptr = CAR; /* NLs are replaced by CRs! */
2125 else
2126 {
2127 if (skip_count == 0)
2128 {
2129 *ptr = NUL; /* end of line */
2130 len = (colnr_T) (ptr - line_start + 1);
2131 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2132 {
2133 error = TRUE;
2134 break;
2135 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002136#ifdef FEAT_PERSISTENT_UNDO
2137 if (read_undo_file)
2138 sha256_update(&sha_ctx, line_start, len);
2139#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002140 ++lnum;
2141 if (--read_count == 0)
2142 {
2143 error = TRUE; /* break loop */
2144 line_start = ptr; /* nothing left to write */
2145 break;
2146 }
2147 }
2148 else
2149 --skip_count;
2150 line_start = ptr + 1;
2151 }
2152 }
2153 }
2154 else
2155 {
2156 --ptr;
2157 while (++ptr, --size >= 0)
2158 {
2159 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2160 continue;
2161 if (c == NUL)
2162 *ptr = NL; /* NULs are replaced by newlines! */
2163 else
2164 {
2165 if (skip_count == 0)
2166 {
2167 *ptr = NUL; /* end of line */
2168 len = (colnr_T)(ptr - line_start + 1);
2169 if (fileformat == EOL_DOS)
2170 {
2171 if (ptr[-1] == CAR) /* remove CR */
2172 {
2173 ptr[-1] = NUL;
2174 --len;
2175 }
2176 /*
2177 * Reading in Dos format, but no CR-LF found!
2178 * When 'fileformats' includes "unix", delete all
2179 * the lines read so far and start all over again.
2180 * Otherwise give an error message later.
2181 */
2182 else if (ff_error != EOL_DOS)
2183 {
2184 if ( try_unix
2185 && !read_stdin
2186 && (read_buffer
2187 || lseek(fd, (off_t)0L, SEEK_SET) == 0))
2188 {
2189 fileformat = EOL_UNIX;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002190 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002191 set_fileformat(EOL_UNIX, OPT_LOCAL);
2192 file_rewind = TRUE;
2193 keep_fileformat = TRUE;
2194 goto retry;
2195 }
2196 ff_error = EOL_DOS;
2197 }
2198 }
2199 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2200 {
2201 error = TRUE;
2202 break;
2203 }
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002204#ifdef FEAT_PERSISTENT_UNDO
2205 if (read_undo_file)
2206 sha256_update(&sha_ctx, line_start, len);
2207#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002208 ++lnum;
2209 if (--read_count == 0)
2210 {
2211 error = TRUE; /* break loop */
2212 line_start = ptr; /* nothing left to write */
2213 break;
2214 }
2215 }
2216 else
2217 --skip_count;
2218 line_start = ptr + 1;
2219 }
2220 }
2221 }
2222 linerest = (long)(ptr - line_start);
2223 ui_breakcheck();
2224 }
2225
2226failed:
2227 /* not an error, max. number of lines reached */
2228 if (error && read_count == 0)
2229 error = FALSE;
2230
2231 /*
2232 * If we get EOF in the middle of a line, note the fact and
2233 * complete the line ourselves.
2234 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2235 */
2236 if (!error
2237 && !got_int
2238 && linerest != 0
2239 && !(!curbuf->b_p_bin
2240 && fileformat == EOL_DOS
2241 && *line_start == Ctrl_Z
2242 && ptr == line_start + 1))
2243 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002244 /* remember for when writing */
2245 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002246 curbuf->b_p_eol = FALSE;
2247 *ptr = NUL;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002248 len = (colnr_T)(ptr - line_start + 1);
2249 if (ml_append(lnum, line_start, len, newfile) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002250 error = TRUE;
2251 else
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002252 {
2253#ifdef FEAT_PERSISTENT_UNDO
2254 if (read_undo_file)
2255 sha256_update(&sha_ctx, line_start, len);
2256#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002257 read_no_eol_lnum = ++lnum;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002258 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002259 }
2260
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002261 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002262 save_file_ff(curbuf); /* remember the current file format */
2263
2264#ifdef FEAT_CRYPT
Bram Moolenaar4cf35c22011-02-25 16:52:17 +01002265 crypt_method_used = use_crypt_method;
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002266 if (cryptkey != NULL)
2267 {
2268 crypt_pop_state();
2269 if (cryptkey != curbuf->b_p_key)
2270 free_crypt_key(cryptkey);
2271 /* don't set cryptkey to NULL, it's used below as a flag that
2272 * encryption was used */
2273 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002274#endif
2275
2276#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002277 /* If editing a new file: set 'fenc' for the current buffer.
2278 * Also for ":read ++edit file". */
2279 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002280 set_string_option_direct((char_u *)"fenc", -1, fenc,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002281 OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 if (fenc_alloced)
2283 vim_free(fenc);
2284# ifdef USE_ICONV
2285 if (iconv_fd != (iconv_t)-1)
2286 {
2287 iconv_close(iconv_fd);
2288 iconv_fd = (iconv_t)-1;
2289 }
2290# endif
2291#endif
2292
2293 if (!read_buffer && !read_stdin)
2294 close(fd); /* errors are ignored */
Bram Moolenaarf05da212009-11-17 16:13:15 +00002295#ifdef HAVE_FD_CLOEXEC
2296 else
2297 {
2298 int fdflags = fcntl(fd, F_GETFD);
2299 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
2300 fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
2301 }
2302#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002303 vim_free(buffer);
2304
2305#ifdef HAVE_DUP
2306 if (read_stdin)
2307 {
2308 /* Use stderr for stdin, makes shell commands work. */
2309 close(0);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00002310 ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002311 }
2312#endif
2313
2314#ifdef FEAT_MBYTE
2315 if (tmpname != NULL)
2316 {
2317 mch_remove(tmpname); /* delete converted file */
2318 vim_free(tmpname);
2319 }
2320#endif
2321 --no_wait_return; /* may wait for return now */
2322
2323 /*
2324 * In recovery mode everything but autocommands is skipped.
2325 */
2326 if (!recoverymode)
2327 {
2328 /* need to delete the last line, which comes from the empty buffer */
2329 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2330 {
2331#ifdef FEAT_NETBEANS_INTG
2332 netbeansFireChanges = 0;
2333#endif
2334 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2335#ifdef FEAT_NETBEANS_INTG
2336 netbeansFireChanges = 1;
2337#endif
2338 --linecnt;
2339 }
2340 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2341 if (filesize == 0)
2342 linecnt = 0;
2343 if (newfile || read_buffer)
Bram Moolenaar7263a772007-05-10 17:35:54 +00002344 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002345 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar7263a772007-05-10 17:35:54 +00002346#ifdef FEAT_DIFF
2347 /* After reading the text into the buffer the diff info needs to
2348 * be updated. */
2349 diff_invalidate(curbuf);
2350#endif
2351#ifdef FEAT_FOLDING
2352 /* All folds in the window are invalid now. Mark them for update
2353 * before triggering autocommands. */
2354 foldUpdateAll(curwin);
2355#endif
2356 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002357 else if (linecnt) /* appended at least one line */
2358 appended_lines_mark(from, linecnt);
2359
Bram Moolenaar071d4272004-06-13 20:20:40 +00002360#ifndef ALWAYS_USE_GUI
2361 /*
2362 * If we were reading from the same terminal as where messages go,
2363 * the screen will have been messed up.
2364 * Switch on raw mode now and clear the screen.
2365 */
2366 if (read_stdin)
2367 {
2368 settmode(TMODE_RAW); /* set to raw mode */
2369 starttermcap();
2370 screenclear();
2371 }
2372#endif
2373
2374 if (got_int)
2375 {
2376 if (!(flags & READ_DUMMY))
2377 {
2378 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2379 if (newfile)
2380 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2381 }
2382 msg_scroll = msg_save;
2383#ifdef FEAT_VIMINFO
2384 check_marks_read();
2385#endif
2386 return OK; /* an interrupt isn't really an error */
2387 }
2388
2389 if (!filtering && !(flags & READ_DUMMY))
2390 {
2391 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2392 c = FALSE;
2393
2394#ifdef UNIX
2395# ifdef S_ISFIFO
2396 if (S_ISFIFO(perm)) /* fifo or socket */
2397 {
2398 STRCAT(IObuff, _("[fifo/socket]"));
2399 c = TRUE;
2400 }
2401# else
2402# ifdef S_IFIFO
2403 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2404 {
2405 STRCAT(IObuff, _("[fifo]"));
2406 c = TRUE;
2407 }
2408# endif
2409# ifdef S_IFSOCK
2410 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2411 {
2412 STRCAT(IObuff, _("[socket]"));
2413 c = TRUE;
2414 }
2415# endif
2416# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002417# ifdef OPEN_CHR_FILES
2418 if (S_ISCHR(perm)) /* or character special */
2419 {
2420 STRCAT(IObuff, _("[character special]"));
2421 c = TRUE;
2422 }
2423# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002424#endif
2425 if (curbuf->b_p_ro)
2426 {
2427 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2428 c = TRUE;
2429 }
2430 if (read_no_eol_lnum)
2431 {
2432 msg_add_eol();
2433 c = TRUE;
2434 }
2435 if (ff_error == EOL_DOS)
2436 {
2437 STRCAT(IObuff, _("[CR missing]"));
2438 c = TRUE;
2439 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 if (split)
2441 {
2442 STRCAT(IObuff, _("[long lines split]"));
2443 c = TRUE;
2444 }
2445#ifdef FEAT_MBYTE
2446 if (notconverted)
2447 {
2448 STRCAT(IObuff, _("[NOT converted]"));
2449 c = TRUE;
2450 }
2451 else if (converted)
2452 {
2453 STRCAT(IObuff, _("[converted]"));
2454 c = TRUE;
2455 }
2456#endif
2457#ifdef FEAT_CRYPT
2458 if (cryptkey != NULL)
2459 {
Bram Moolenaar4cf35c22011-02-25 16:52:17 +01002460 if (crypt_method_used == 1)
2461 STRCAT(IObuff, _("[blowfish]"));
2462 else
2463 STRCAT(IObuff, _("[crypted]"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002464 c = TRUE;
2465 }
2466#endif
2467#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002468 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002470 sprintf((char *)IObuff + STRLEN(IObuff),
2471 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002472 c = TRUE;
2473 }
2474 else if (illegal_byte > 0)
2475 {
2476 sprintf((char *)IObuff + STRLEN(IObuff),
2477 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2478 c = TRUE;
2479 }
2480 else
2481#endif
2482 if (error)
2483 {
2484 STRCAT(IObuff, _("[READ ERRORS]"));
2485 c = TRUE;
2486 }
2487 if (msg_add_fileformat(fileformat))
2488 c = TRUE;
2489#ifdef FEAT_CRYPT
2490 if (cryptkey != NULL)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002491 msg_add_lines(c, (long)linecnt, filesize
Bram Moolenaar80794b12010-06-13 05:20:42 +02002492 - CRYPT_MAGIC_LEN
2493 - crypt_salt_len[use_crypt_method]
2494 - crypt_seed_len[use_crypt_method]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002495 else
2496#endif
2497 msg_add_lines(c, (long)linecnt, filesize);
2498
2499 vim_free(keep_msg);
2500 keep_msg = NULL;
2501 msg_scrolled_ign = TRUE;
2502#ifdef ALWAYS_USE_GUI
2503 /* Don't show the message when reading stdin, it would end up in a
2504 * message box (which might be shown when exiting!) */
2505 if (read_stdin || read_buffer)
2506 p = msg_may_trunc(FALSE, IObuff);
2507 else
2508#endif
2509 p = msg_trunc_attr(IObuff, FALSE, 0);
2510 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002511 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002512 /* Need to repeat the message after redrawing when:
2513 * - When reading from stdin (the screen will be cleared next).
2514 * - When restart_edit is set (otherwise there will be a delay
2515 * before redrawing).
2516 * - When the screen was scrolled but there is no wait-return
2517 * prompt. */
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002518 set_keep_msg(p, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 msg_scrolled_ign = FALSE;
2520 }
2521
2522 /* with errors writing the file requires ":w!" */
2523 if (newfile && (error
2524#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002525 || conv_error != 0
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002526 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527#endif
2528 ))
2529 curbuf->b_p_ro = TRUE;
2530
2531 u_clearline(); /* cannot use "U" command after adding lines */
2532
2533 /*
2534 * In Ex mode: cursor at last new line.
2535 * Otherwise: cursor at first new line.
2536 */
2537 if (exmode_active)
2538 curwin->w_cursor.lnum = from + linecnt;
2539 else
2540 curwin->w_cursor.lnum = from + 1;
2541 check_cursor_lnum();
2542 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2543
2544 /*
2545 * Set '[ and '] marks to the newly read lines.
2546 */
2547 curbuf->b_op_start.lnum = from + 1;
2548 curbuf->b_op_start.col = 0;
2549 curbuf->b_op_end.lnum = from + linecnt;
2550 curbuf->b_op_end.col = 0;
Bram Moolenaar03f48552006-02-28 23:52:23 +00002551
2552#ifdef WIN32
2553 /*
2554 * Work around a weird problem: When a file has two links (only
2555 * possible on NTFS) and we write through one link, then stat() it
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00002556 * through the other link, the timestamp information may be wrong.
Bram Moolenaar03f48552006-02-28 23:52:23 +00002557 * It's correct again after reading the file, thus reset the timestamp
2558 * here.
2559 */
2560 if (newfile && !read_stdin && !read_buffer
2561 && mch_stat((char *)fname, &st) >= 0)
2562 {
2563 buf_store_time(curbuf, &st, fname);
2564 curbuf->b_mtime_read = curbuf->b_mtime;
2565 }
2566#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002567 }
2568 msg_scroll = msg_save;
2569
2570#ifdef FEAT_VIMINFO
2571 /*
2572 * Get the marks before executing autocommands, so they can be used there.
2573 */
2574 check_marks_read();
2575#endif
2576
Bram Moolenaar071d4272004-06-13 20:20:40 +00002577 /*
2578 * Trick: We remember if the last line of the read didn't have
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002579 * an eol even when 'binary' is off, for when writing it again with
2580 * 'binary' on. This is required for
Bram Moolenaar071d4272004-06-13 20:20:40 +00002581 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
2582 */
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002583 curbuf->b_no_eol_lnum = read_no_eol_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002584
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02002585 /* When reloading a buffer put the cursor at the first line that is
2586 * different. */
2587 if (flags & READ_KEEP_UNDO)
2588 u_find_first_changed();
2589
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002590#ifdef FEAT_PERSISTENT_UNDO
2591 /*
2592 * When opening a new file locate undo info and read it.
2593 */
2594 if (read_undo_file)
2595 {
2596 char_u hash[UNDO_HASH_SIZE];
2597
2598 sha256_finish(&sha_ctx, hash);
Bram Moolenaar6ed8ed82010-05-30 20:40:11 +02002599 u_read_undo(NULL, hash, fname);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02002600 }
2601#endif
2602
Bram Moolenaardf177f62005-02-22 08:39:57 +00002603#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 if (!read_stdin && !read_buffer)
2605 {
2606 int m = msg_scroll;
2607 int n = msg_scrolled;
2608
2609 /* Save the fileformat now, otherwise the buffer will be considered
2610 * modified if the format/encoding was automatically detected. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002611 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002612 save_file_ff(curbuf);
2613
2614 /*
2615 * The output from the autocommands should not overwrite anything and
2616 * should not be overwritten: Set msg_scroll, restore its value if no
2617 * output was done.
2618 */
2619 msg_scroll = TRUE;
2620 if (filtering)
2621 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2622 FALSE, curbuf, eap);
2623 else if (newfile)
2624 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2625 FALSE, curbuf, eap);
2626 else
2627 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2628 FALSE, NULL, eap);
2629 if (msg_scrolled == n)
2630 msg_scroll = m;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002631# ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002632 if (aborting()) /* autocmds may abort script processing */
2633 return FAIL;
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01002634# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002635 }
2636#endif
2637
2638 if (recoverymode && error)
2639 return FAIL;
2640 return OK;
2641}
2642
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002643#ifdef OPEN_CHR_FILES
2644/*
2645 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2646 * which is the name of files used for process substitution output by
2647 * some shells on some operating systems, e.g., bash on SunOS.
2648 * Do not accept "/dev/fd/[012]", opening these may hang Vim.
2649 */
2650 static int
2651is_dev_fd_file(fname)
2652 char_u *fname;
2653{
2654 return (STRNCMP(fname, "/dev/fd/", 8) == 0
2655 && VIM_ISDIGIT(fname[8])
2656 && *skipdigits(fname + 9) == NUL
2657 && (fname[9] != NUL
2658 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
2659}
2660#endif
2661
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002662#ifdef FEAT_MBYTE
2663
2664/*
2665 * From the current line count and characters read after that, estimate the
2666 * line number where we are now.
2667 * Used for error messages that include a line number.
2668 */
2669 static linenr_T
2670readfile_linenr(linecnt, p, endp)
2671 linenr_T linecnt; /* line count before reading more bytes */
2672 char_u *p; /* start of more bytes read */
2673 char_u *endp; /* end of more bytes read */
2674{
2675 char_u *s;
2676 linenr_T lnum;
2677
2678 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2679 for (s = p; s < endp; ++s)
2680 if (*s == '\n')
2681 ++lnum;
2682 return lnum;
2683}
2684#endif
2685
Bram Moolenaar071d4272004-06-13 20:20:40 +00002686/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002687 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2688 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002689 * Returns OK or FAIL.
2690 */
2691 int
2692prep_exarg(eap, buf)
2693 exarg_T *eap;
2694 buf_T *buf;
2695{
2696 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2697#ifdef FEAT_MBYTE
2698 + STRLEN(buf->b_p_fenc)
2699#endif
2700 + 15));
2701 if (eap->cmd == NULL)
2702 return FAIL;
2703
2704#ifdef FEAT_MBYTE
2705 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2706 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
Bram Moolenaar195d6352005-12-19 22:08:24 +00002707 eap->bad_char = buf->b_bad_char;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002708#else
2709 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2710#endif
2711 eap->force_ff = 7;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002712
2713 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002714 eap->read_edit = FALSE;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002715 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002716 return OK;
2717}
2718
Bram Moolenaarad875fb2013-07-24 15:02:03 +02002719/*
2720 * Set default or forced 'fileformat' and 'binary'.
2721 */
2722 void
2723set_file_options(set_options, eap)
2724 int set_options;
2725 exarg_T *eap;
2726{
2727 /* set default 'fileformat' */
2728 if (set_options)
2729 {
2730 if (eap != NULL && eap->force_ff != 0)
2731 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
2732 else if (*p_ffs != NUL)
2733 set_fileformat(default_fileformat(), OPT_LOCAL);
2734 }
2735
2736 /* set or reset 'binary' */
2737 if (eap != NULL && eap->force_bin != 0)
2738 {
2739 int oldval = curbuf->b_p_bin;
2740
2741 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
2742 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
2743 }
2744}
2745
2746#if defined(FEAT_MBYTE) || defined(PROTO)
2747/*
2748 * Set forced 'fileencoding'.
2749 */
2750 void
2751set_forced_fenc(eap)
2752 exarg_T *eap;
2753{
2754 if (eap->force_enc != 0)
2755 {
2756 char_u *fenc = enc_canonize(eap->cmd + eap->force_enc);
2757
2758 if (fenc != NULL)
2759 set_string_option_direct((char_u *)"fenc", -1,
2760 fenc, OPT_FREE|OPT_LOCAL, 0);
2761 vim_free(fenc);
2762 }
2763}
2764
Bram Moolenaar071d4272004-06-13 20:20:40 +00002765/*
2766 * Find next fileencoding to use from 'fileencodings'.
2767 * "pp" points to fenc_next. It's advanced to the next item.
2768 * When there are no more items, an empty string is returned and *pp is set to
2769 * NULL.
2770 * When *pp is not set to NULL, the result is in allocated memory.
2771 */
2772 static char_u *
2773next_fenc(pp)
2774 char_u **pp;
2775{
2776 char_u *p;
2777 char_u *r;
2778
2779 if (**pp == NUL)
2780 {
2781 *pp = NULL;
2782 return (char_u *)"";
2783 }
2784 p = vim_strchr(*pp, ',');
2785 if (p == NULL)
2786 {
2787 r = enc_canonize(*pp);
2788 *pp += STRLEN(*pp);
2789 }
2790 else
2791 {
2792 r = vim_strnsave(*pp, (int)(p - *pp));
2793 *pp = p + 1;
2794 if (r != NULL)
2795 {
2796 p = enc_canonize(r);
2797 vim_free(r);
2798 r = p;
2799 }
2800 }
2801 if (r == NULL) /* out of memory */
2802 {
2803 r = (char_u *)"";
2804 *pp = NULL;
2805 }
2806 return r;
2807}
2808
2809# ifdef FEAT_EVAL
2810/*
2811 * Convert a file with the 'charconvert' expression.
2812 * This closes the file which is to be read, converts it and opens the
2813 * resulting file for reading.
2814 * Returns name of the resulting converted file (the caller should delete it
2815 * after reading it).
2816 * Returns NULL if the conversion failed ("*fdp" is not set) .
2817 */
2818 static char_u *
2819readfile_charconvert(fname, fenc, fdp)
2820 char_u *fname; /* name of input file */
2821 char_u *fenc; /* converted from */
2822 int *fdp; /* in/out: file descriptor of file */
2823{
2824 char_u *tmpname;
2825 char_u *errmsg = NULL;
2826
2827 tmpname = vim_tempname('r');
2828 if (tmpname == NULL)
2829 errmsg = (char_u *)_("Can't find temp file for conversion");
2830 else
2831 {
2832 close(*fdp); /* close the input file, ignore errors */
2833 *fdp = -1;
2834 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2835 fname, tmpname) == FAIL)
2836 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2837 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2838 O_RDONLY | O_EXTRA, 0)) < 0)
2839 errmsg = (char_u *)_("can't read output of 'charconvert'");
2840 }
2841
2842 if (errmsg != NULL)
2843 {
2844 /* Don't use emsg(), it breaks mappings, the retry with
2845 * another type of conversion might still work. */
2846 MSG(errmsg);
2847 if (tmpname != NULL)
2848 {
2849 mch_remove(tmpname); /* delete converted file */
2850 vim_free(tmpname);
2851 tmpname = NULL;
2852 }
2853 }
2854
2855 /* If the input file is closed, open it (caller should check for error). */
2856 if (*fdp < 0)
2857 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2858
2859 return tmpname;
2860}
2861# endif
2862
2863#endif
2864
2865#ifdef FEAT_VIMINFO
2866/*
2867 * Read marks for the current buffer from the viminfo file, when we support
2868 * buffer marks and the buffer has a name.
2869 */
2870 static void
2871check_marks_read()
2872{
2873 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2874 && curbuf->b_ffname != NULL)
Bram Moolenaard812df62008-11-09 12:46:09 +00002875 read_viminfo(NULL, VIF_WANT_MARKS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002876
2877 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2878 * the ' parameter after opening a buffer. */
2879 curbuf->b_marks_read = TRUE;
2880}
2881#endif
2882
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02002883#if defined(FEAT_CRYPT) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002884/*
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002885 * Get the crypt method used for a file from "ptr[len]", the magic text at the
2886 * start of the file.
2887 * Returns -1 when no encryption used.
2888 */
2889 static int
Bram Moolenaar49771f42010-07-20 17:32:38 +02002890crypt_method_from_magic(ptr, len)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002891 char *ptr;
2892 int len;
2893{
2894 int i;
2895
2896 for (i = 0; i < (int)(sizeof(crypt_magic) / sizeof(crypt_magic[0])); i++)
2897 {
Bram Moolenaar80794b12010-06-13 05:20:42 +02002898 if (len < (CRYPT_MAGIC_LEN + crypt_salt_len[i] + crypt_seed_len[i]))
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002899 continue;
2900 if (memcmp(ptr, crypt_magic[i], CRYPT_MAGIC_LEN) == 0)
2901 return i;
2902 }
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002903
Bram Moolenaar442b4222010-05-24 21:34:22 +02002904 i = (int)STRLEN(crypt_magic_head);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002905 if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0)
2906 EMSG(_("E821: File is encrypted with unknown method"));
2907
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002908 return -1;
2909}
2910
2911/*
2912 * Check for magic number used for encryption. Applies to the current buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2914 * *filesizep are updated.
2915 * Return the (new) encryption key, NULL for no encryption.
2916 */
2917 static char_u *
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002918check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, fname, did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002919 char_u *cryptkey; /* previous encryption key or NULL */
2920 char_u *ptr; /* pointer to read bytes */
2921 long *sizep; /* length of read bytes */
Bram Moolenaar914703b2010-05-31 21:59:46 +02002922 off_t *filesizep; /* nr of bytes used from file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 int newfile; /* editing a new buffer */
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002924 char_u *fname; /* file name to display */
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002925 int *did_ask; /* flag: whether already asked for key */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926{
Bram Moolenaar49771f42010-07-20 17:32:38 +02002927 int method = crypt_method_from_magic((char *)ptr, *sizep);
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002928 int b_p_ro = curbuf->b_p_ro;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002929
2930 if (method >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002931 {
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002932 /* Mark the buffer as read-only until the decryption has taken place.
2933 * Avoids accidentally overwriting the file with garbage. */
2934 curbuf->b_p_ro = TRUE;
2935
Bram Moolenaar49771f42010-07-20 17:32:38 +02002936 set_crypt_method(curbuf, method);
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002937 if (method > 0)
2938 (void)blowfish_self_test();
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002939 if (cryptkey == NULL && !*did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940 {
2941 if (*curbuf->b_p_key)
2942 cryptkey = curbuf->b_p_key;
2943 else
2944 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002945 /* When newfile is TRUE, store the typed key in the 'key'
2946 * option and don't free it. bf needs hash of the key saved.
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002947 * Don't ask for the key again when first time Enter was hit.
2948 * Happens when retrying to detect encoding. */
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002949 smsg((char_u *)_(need_key_msg), fname);
2950 msg_scroll = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951 cryptkey = get_crypt_key(newfile, FALSE);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002952 *did_ask = TRUE;
2953
Bram Moolenaar071d4272004-06-13 20:20:40 +00002954 /* check if empty key entered */
2955 if (cryptkey != NULL && *cryptkey == NUL)
2956 {
2957 if (cryptkey != curbuf->b_p_key)
2958 vim_free(cryptkey);
2959 cryptkey = NULL;
2960 }
2961 }
2962 }
2963
2964 if (cryptkey != NULL)
2965 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002966 int seed_len = crypt_seed_len[method];
Bram Moolenaar80794b12010-06-13 05:20:42 +02002967 int salt_len = crypt_salt_len[method];
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002968
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002969 crypt_push_state();
2970 use_crypt_method = method;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002971 if (method == 0)
2972 crypt_init_keys(cryptkey);
2973 else
2974 {
Bram Moolenaar80794b12010-06-13 05:20:42 +02002975 bf_key_init(cryptkey, ptr + CRYPT_MAGIC_LEN, salt_len);
Bram Moolenaar4d504a32014-02-11 15:23:32 +01002976 bf_cfb_init(ptr + CRYPT_MAGIC_LEN + salt_len, seed_len);
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002977 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978
2979 /* Remove magic number from the text */
Bram Moolenaar80794b12010-06-13 05:20:42 +02002980 *filesizep += CRYPT_MAGIC_LEN + salt_len + seed_len;
2981 *sizep -= CRYPT_MAGIC_LEN + salt_len + seed_len;
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02002982 mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN + salt_len + seed_len,
2983 (size_t)*sizep);
Bram Moolenaarcf81aef2013-08-25 17:46:08 +02002984 /* Restore the read-only flag. */
2985 curbuf->b_p_ro = b_p_ro;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002986 }
2987 }
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002988 /* When starting to edit a new file which does not have encryption, clear
2989 * the 'key' option, except when starting up (called with -x argument) */
Bram Moolenaarfa0ff9a2010-07-25 16:05:19 +02002990 else if (newfile && *curbuf->b_p_key != NUL && !starting)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2992
2993 return cryptkey;
2994}
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02002995
2996/*
2997 * Check for magic number used for encryption. Applies to the current buffer.
2998 * If found and decryption is possible returns OK;
2999 */
3000 int
3001prepare_crypt_read(fp)
3002 FILE *fp;
3003{
3004 int method;
Bram Moolenaar80794b12010-06-13 05:20:42 +02003005 char_u buffer[CRYPT_MAGIC_LEN + CRYPT_SALT_LEN_MAX
3006 + CRYPT_SEED_LEN_MAX + 2];
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003007
3008 if (fread(buffer, CRYPT_MAGIC_LEN, 1, fp) != 1)
3009 return FAIL;
Bram Moolenaar49771f42010-07-20 17:32:38 +02003010 method = crypt_method_from_magic((char *)buffer,
Bram Moolenaar80794b12010-06-13 05:20:42 +02003011 CRYPT_MAGIC_LEN +
Bram Moolenaarcc448b32010-07-14 16:52:17 +02003012 CRYPT_SEED_LEN_MAX +
3013 CRYPT_SALT_LEN_MAX);
Bram Moolenaar49771f42010-07-20 17:32:38 +02003014 if (method < 0 || method != get_crypt_method(curbuf))
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003015 return FAIL;
3016
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003017 crypt_push_state();
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003018 if (method == 0)
3019 crypt_init_keys(curbuf->b_p_key);
3020 else
3021 {
Bram Moolenaar80794b12010-06-13 05:20:42 +02003022 int salt_len = crypt_salt_len[method];
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003023 int seed_len = crypt_seed_len[method];
3024
Bram Moolenaar80794b12010-06-13 05:20:42 +02003025 if (fread(buffer, salt_len + seed_len, 1, fp) != 1)
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003026 return FAIL;
Bram Moolenaar80794b12010-06-13 05:20:42 +02003027 bf_key_init(curbuf->b_p_key, buffer, salt_len);
Bram Moolenaar4d504a32014-02-11 15:23:32 +01003028 bf_cfb_init(buffer + salt_len, seed_len);
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003029 }
3030 return OK;
3031}
3032
3033/*
3034 * Prepare for writing encrypted bytes for buffer "buf".
3035 * Returns a pointer to an allocated header of length "*lenp".
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003036 * When out of memory returns NULL.
3037 * Otherwise calls crypt_push_state(), call crypt_pop_state() later.
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003038 */
3039 char_u *
3040prepare_crypt_write(buf, lenp)
3041 buf_T *buf;
3042 int *lenp;
3043{
3044 char_u *header;
Bram Moolenaar49771f42010-07-20 17:32:38 +02003045 int seed_len = crypt_seed_len[get_crypt_method(buf)];
3046 int salt_len = crypt_salt_len[get_crypt_method(buf)];
Bram Moolenaar80794b12010-06-13 05:20:42 +02003047 char_u *salt;
3048 char_u *seed;
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003049
Bram Moolenaar80794b12010-06-13 05:20:42 +02003050 header = alloc_clear(CRYPT_MAGIC_LEN + CRYPT_SALT_LEN_MAX
3051 + CRYPT_SEED_LEN_MAX + 2);
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003052 if (header != NULL)
3053 {
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003054 crypt_push_state();
Bram Moolenaar49771f42010-07-20 17:32:38 +02003055 use_crypt_method = get_crypt_method(buf); /* select zip or blowfish */
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003056 vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method],
3057 CRYPT_MAGIC_LEN);
Bram Moolenaar49771f42010-07-20 17:32:38 +02003058 if (use_crypt_method == 0)
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003059 crypt_init_keys(buf->b_p_key);
3060 else
3061 {
Bram Moolenaar80794b12010-06-13 05:20:42 +02003062 /* Using blowfish, add salt and seed. */
3063 salt = header + CRYPT_MAGIC_LEN;
3064 seed = salt + salt_len;
3065 sha2_seed(salt, salt_len, seed, seed_len);
3066 bf_key_init(buf->b_p_key, salt, salt_len);
Bram Moolenaar4d504a32014-02-11 15:23:32 +01003067 bf_cfb_init(seed, seed_len);
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003068 }
3069 }
Bram Moolenaar80794b12010-06-13 05:20:42 +02003070 *lenp = CRYPT_MAGIC_LEN + salt_len + seed_len;
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02003071 return header;
3072}
3073
Bram Moolenaar80794b12010-06-13 05:20:42 +02003074#endif /* FEAT_CRYPT */
3075
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076#ifdef UNIX
3077 static void
3078set_file_time(fname, atime, mtime)
3079 char_u *fname;
3080 time_t atime; /* access time */
3081 time_t mtime; /* modification time */
3082{
3083# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
3084 struct utimbuf buf;
3085
3086 buf.actime = atime;
3087 buf.modtime = mtime;
3088 (void)utime((char *)fname, &buf);
3089# else
3090# if defined(HAVE_UTIMES)
3091 struct timeval tvp[2];
3092
3093 tvp[0].tv_sec = atime;
3094 tvp[0].tv_usec = 0;
3095 tvp[1].tv_sec = mtime;
3096 tvp[1].tv_usec = 0;
3097# ifdef NeXT
3098 (void)utimes((char *)fname, tvp);
3099# else
3100 (void)utimes((char *)fname, (const struct timeval *)&tvp);
3101# endif
3102# endif
3103# endif
3104}
3105#endif /* UNIX */
3106
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003107#if defined(VMS) && !defined(MIN)
3108/* Older DECC compiler for VAX doesn't define MIN() */
3109# define MIN(a, b) ((a) < (b) ? (a) : (b))
3110#endif
3111
Bram Moolenaar071d4272004-06-13 20:20:40 +00003112/*
Bram Moolenaar5386a122007-06-28 20:02:32 +00003113 * Return TRUE if a file appears to be read-only from the file permissions.
3114 */
3115 int
3116check_file_readonly(fname, perm)
3117 char_u *fname; /* full path to file */
3118 int perm; /* known permissions on file */
3119{
3120#ifndef USE_MCH_ACCESS
3121 int fd = 0;
3122#endif
3123
3124 return (
3125#ifdef USE_MCH_ACCESS
3126# ifdef UNIX
3127 (perm & 0222) == 0 ||
3128# endif
3129 mch_access((char *)fname, W_OK)
3130#else
3131 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
3132 ? TRUE : (close(fd), FALSE)
3133#endif
3134 );
3135}
3136
3137
3138/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00003139 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00003140 *
3141 * We do our own buffering here because fwrite() is so slow.
3142 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00003143 * If "forceit" is true, we don't care for errors when attempting backups.
3144 * In case of an error everything possible is done to restore the original
Bram Moolenaare37d50a2008-08-06 17:06:04 +00003145 * file. But when "forceit" is TRUE, we risk losing it.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003146 *
3147 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
3148 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003149 *
3150 * This function must NOT use NameBuff (because it's called by autowrite()).
3151 *
3152 * return FAIL for failure, OK otherwise
3153 */
3154 int
3155buf_write(buf, fname, sfname, start, end, eap, append, forceit,
3156 reset_changed, filtering)
3157 buf_T *buf;
3158 char_u *fname;
3159 char_u *sfname;
3160 linenr_T start, end;
3161 exarg_T *eap; /* for forced 'ff' and 'fenc', can be
3162 NULL! */
Bram Moolenaar292ad192005-12-11 21:29:51 +00003163 int append; /* append to the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003164 int forceit;
3165 int reset_changed;
3166 int filtering;
3167{
3168 int fd;
3169 char_u *backup = NULL;
3170 int backup_copy = FALSE; /* copy the original file? */
3171 int dobackup;
3172 char_u *ffname;
3173 char_u *wfname = NULL; /* name of file to write to */
3174 char_u *s;
3175 char_u *ptr;
3176 char_u c;
3177 int len;
3178 linenr_T lnum;
3179 long nchars;
3180 char_u *errmsg = NULL;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003181 int errmsg_allocated = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003182 char_u *errnum = NULL;
3183 char_u *buffer;
3184 char_u smallbuf[SMBUFSIZE];
3185 char_u *backup_ext;
3186 int bufsize;
3187 long perm; /* file permissions */
3188 int retval = OK;
3189 int newfile = FALSE; /* TRUE if file doesn't exist yet */
3190 int msg_save = msg_scroll;
3191 int overwriting; /* TRUE if writing over original */
3192 int no_eol = FALSE; /* no end-of-line written */
3193 int device = FALSE; /* writing to a device */
3194 struct stat st_old;
3195 int prev_got_int = got_int;
3196 int file_readonly = FALSE; /* overwritten file is read-only */
3197 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
3198#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
3199 int made_writable = FALSE; /* 'w' bit has been set */
3200#endif
3201 /* writing everything */
3202 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
3203#ifdef FEAT_AUTOCMD
3204 linenr_T old_line_count = buf->b_ml.ml_line_count;
3205#endif
3206 int attr;
3207 int fileformat;
3208 int write_bin;
3209 struct bw_info write_info; /* info for buf_write_bytes() */
3210#ifdef FEAT_MBYTE
3211 int converted = FALSE;
3212 int notconverted = FALSE;
3213 char_u *fenc; /* effective 'fileencoding' */
3214 char_u *fenc_tofree = NULL; /* allocated "fenc" */
3215#endif
3216#ifdef HAS_BW_FLAGS
3217 int wb_flags = 0;
3218#endif
3219#ifdef HAVE_ACL
3220 vim_acl_T acl = NULL; /* ACL copied from original file to
3221 backup or new file */
3222#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02003223#ifdef FEAT_PERSISTENT_UNDO
3224 int write_undo_file = FALSE;
3225 context_sha256_T sha_ctx;
3226#endif
Bram Moolenaar4cf35c22011-02-25 16:52:17 +01003227#ifdef FEAT_CRYPT
3228 int crypt_method_used;
3229#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003230
3231 if (fname == NULL || *fname == NUL) /* safety check */
3232 return FAIL;
Bram Moolenaar70d60e92009-12-31 13:53:33 +00003233 if (buf->b_ml.ml_mfp == NULL)
3234 {
3235 /* This can happen during startup when there is a stray "w" in the
3236 * vimrc file. */
3237 EMSG(_(e_emptybuf));
3238 return FAIL;
3239 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240
3241 /*
3242 * Disallow writing from .exrc and .vimrc in current directory for
3243 * security reasons.
3244 */
3245 if (check_secure())
3246 return FAIL;
3247
3248 /* Avoid a crash for a long name. */
3249 if (STRLEN(fname) >= MAXPATHL)
3250 {
3251 EMSG(_(e_longname));
3252 return FAIL;
3253 }
3254
3255#ifdef FEAT_MBYTE
3256 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
3257 write_info.bw_conv_buf = NULL;
3258 write_info.bw_conv_error = FALSE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003259 write_info.bw_conv_error_lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003260 write_info.bw_restlen = 0;
3261# ifdef USE_ICONV
3262 write_info.bw_iconv_fd = (iconv_t)-1;
3263# endif
3264#endif
3265
Bram Moolenaardf177f62005-02-22 08:39:57 +00003266 /* After writing a file changedtick changes but we don't want to display
3267 * the line. */
3268 ex_no_reprint = TRUE;
3269
Bram Moolenaar071d4272004-06-13 20:20:40 +00003270 /*
3271 * If there is no file name yet, use the one for the written file.
3272 * BF_NOTEDITED is set to reflect this (in case the write fails).
3273 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003274 * Don't do this when appending.
3275 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003276 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003277 if (buf->b_ffname == NULL
3278 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00003279 && whole
3280 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00003281#ifdef FEAT_QUICKFIX
3282 && !bt_nofile(buf)
3283#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003284 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00003285 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003286 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
3287 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003288 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003290 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003291 }
3292
3293 if (sfname == NULL)
3294 sfname = fname;
3295 /*
3296 * For Unix: Use the short file name whenever possible.
3297 * Avoids problems with networks and when directory names are changed.
3298 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
3299 * another directory, which we don't detect
3300 */
3301 ffname = fname; /* remember full fname */
3302#ifdef UNIX
3303 fname = sfname;
3304#endif
3305
3306 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
3307 overwriting = TRUE;
3308 else
3309 overwriting = FALSE;
3310
3311 if (exiting)
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003312 settmode(TMODE_COOK); /* when exiting allow typeahead now */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003313
3314 ++no_wait_return; /* don't wait for return yet */
3315
3316 /*
3317 * Set '[ and '] marks to the lines to be written.
3318 */
3319 buf->b_op_start.lnum = start;
3320 buf->b_op_start.col = 0;
3321 buf->b_op_end.lnum = end;
3322 buf->b_op_end.col = 0;
3323
3324#ifdef FEAT_AUTOCMD
3325 {
3326 aco_save_T aco;
3327 int buf_ffname = FALSE;
3328 int buf_sfname = FALSE;
3329 int buf_fname_f = FALSE;
3330 int buf_fname_s = FALSE;
3331 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003332 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003333 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003334
3335 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003336 * Apply PRE autocommands.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337 * Set curbuf to the buffer to be written.
3338 * Careful: The autocommands may call buf_write() recursively!
3339 */
3340 if (ffname == buf->b_ffname)
3341 buf_ffname = TRUE;
3342 if (sfname == buf->b_sfname)
3343 buf_sfname = TRUE;
3344 if (fname == buf->b_ffname)
3345 buf_fname_f = TRUE;
3346 if (fname == buf->b_sfname)
3347 buf_fname_s = TRUE;
3348
3349 /* set curwin/curbuf to buf and save a few things */
3350 aucmd_prepbuf(&aco, buf);
3351
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 */
3423 if (!buf_valid(buf))
3424 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 */
3576#if defined(UNIX) && !defined(ARCHIE)
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 Moolenaar043545e2006-10-10 16:44:07 +00003619# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
3620 /* 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)
3722 struct stat st;
3723#endif
3724
3725 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3726 backup_copy = TRUE;
3727#if defined(UNIX) || defined(WIN32)
3728 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3729 {
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 */
3816 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3817 {
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. */
3824 if ((bkc_flags & BKC_BREAKSYMLINK)
3825 && lstat_res == 0
3826 && st.st_ino != st_old.st_ino)
3827 backup_copy = FALSE;
3828
3829 /* Hardlinks. */
3830 if ((bkc_flags & BKC_BREAKHARDLINK)
3831 && 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. */
3837 if ((bkc_flags & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname))
3838 backup_copy = FALSE;
3839
3840 /* Hardlinks. */
3841 if ((bkc_flags & BKC_BREAKHARDLINK) && mch_is_hard_link(fname))
3842 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;
3861 struct stat st_new;
3862 char_u *dirp;
3863 char_u *rootname;
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003864#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865 int did_set_shortname;
3866#endif
3867
3868 copybuf = alloc(BUFSIZE + 1);
3869 if (copybuf == NULL)
3870 {
3871 some_error = TRUE; /* out of memory */
3872 goto nobackup;
3873 }
3874
3875 /*
3876 * Try to make the backup in each directory in the 'bdir' option.
3877 *
3878 * Unix semantics has it, that we may have a writable file,
3879 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3880 * - the directory is not writable,
3881 * - the file may be a symbolic link,
3882 * - the file may belong to another user/group, etc.
3883 *
3884 * For these reasons, the existing writable file must be truncated
3885 * and reused. Creation of a backup COPY will be attempted.
3886 */
3887 dirp = p_bdir;
3888 while (*dirp)
3889 {
3890#ifdef UNIX
3891 st_new.st_ino = 0;
3892 st_new.st_dev = 0;
3893 st_new.st_gid = 0;
3894#endif
3895
3896 /*
3897 * Isolate one directory name, using an entry in 'bdir'.
3898 */
3899 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3900 rootname = get_file_in_dir(fname, copybuf);
3901 if (rootname == NULL)
3902 {
3903 some_error = TRUE; /* out of memory */
3904 goto nobackup;
3905 }
3906
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003907#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003908 did_set_shortname = FALSE;
3909#endif
3910
3911 /*
3912 * May try twice if 'shortname' not set.
3913 */
3914 for (;;)
3915 {
3916 /*
3917 * Make backup file name.
3918 */
3919 backup = buf_modname(
3920#ifdef SHORT_FNAME
3921 TRUE,
3922#else
3923 (buf->b_p_sn || buf->b_shortname),
3924#endif
3925 rootname, backup_ext, FALSE);
3926 if (backup == NULL)
3927 {
3928 vim_free(rootname);
3929 some_error = TRUE; /* out of memory */
3930 goto nobackup;
3931 }
3932
3933 /*
3934 * Check if backup file already exists.
3935 */
3936 if (mch_stat((char *)backup, &st_new) >= 0)
3937 {
3938#ifdef UNIX
3939 /*
3940 * Check if backup file is same as original file.
3941 * May happen when modname() gave the same file back.
3942 * E.g. silly link, or file name-length reached.
3943 * If we don't check here, we either ruin the file
3944 * when copying or erase it after writing. jw.
3945 */
3946 if (st_new.st_dev == st_old.st_dev
3947 && st_new.st_ino == st_old.st_ino)
3948 {
3949 vim_free(backup);
3950 backup = NULL; /* no backup file to delete */
3951# ifndef SHORT_FNAME
3952 /*
3953 * may try again with 'shortname' set
3954 */
3955 if (!(buf->b_shortname || buf->b_p_sn))
3956 {
3957 buf->b_shortname = TRUE;
3958 did_set_shortname = TRUE;
3959 continue;
3960 }
3961 /* setting shortname didn't help */
3962 if (did_set_shortname)
3963 buf->b_shortname = FALSE;
3964# endif
3965 break;
3966 }
3967#endif
3968
3969 /*
3970 * If we are not going to keep the backup file, don't
3971 * delete an existing one, try to use another name.
3972 * Change one character, just before the extension.
3973 */
3974 if (!p_bk)
3975 {
3976 wp = backup + STRLEN(backup) - 1
3977 - STRLEN(backup_ext);
3978 if (wp < backup) /* empty file name ??? */
3979 wp = backup;
3980 *wp = 'z';
3981 while (*wp > 'a'
3982 && mch_stat((char *)backup, &st_new) >= 0)
3983 --*wp;
3984 /* They all exist??? Must be something wrong. */
3985 if (*wp == 'a')
3986 {
3987 vim_free(backup);
3988 backup = NULL;
3989 }
3990 }
3991 }
3992 break;
3993 }
3994 vim_free(rootname);
3995
3996 /*
3997 * Try to create the backup file
3998 */
3999 if (backup != NULL)
4000 {
4001 /* remove old backup, if present */
4002 mch_remove(backup);
4003 /* Open with O_EXCL to avoid the file being created while
4004 * we were sleeping (symlink hacker attack?) */
4005 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00004006 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
4007 perm & 0777);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004008 if (bfd < 0)
4009 {
4010 vim_free(backup);
4011 backup = NULL;
4012 }
4013 else
4014 {
4015 /* set file protection same as original file, but
4016 * strip s-bit */
4017 (void)mch_setperm(backup, perm & 0777);
4018
4019#ifdef UNIX
4020 /*
4021 * Try to set the group of the backup same as the
4022 * original file. If this fails, set the protection
4023 * bits for the group same as the protection bits for
4024 * others.
4025 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00004026 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00004027# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00004028 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00004029# endif
4030 )
4031 mch_setperm(backup,
4032 (perm & 0707) | ((perm & 07) << 3));
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004033# if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004034 mch_copy_sec(fname, backup);
4035# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004036#endif
4037
4038 /*
4039 * copy the file.
4040 */
4041 write_info.bw_fd = bfd;
4042 write_info.bw_buf = copybuf;
4043#ifdef HAS_BW_FLAGS
4044 write_info.bw_flags = FIO_NOCONVERT;
4045#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004046 while ((write_info.bw_len = read_eintr(fd, copybuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004047 BUFSIZE)) > 0)
4048 {
4049 if (buf_write_bytes(&write_info) == FAIL)
4050 {
4051 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
4052 break;
4053 }
4054 ui_breakcheck();
4055 if (got_int)
4056 {
4057 errmsg = (char_u *)_(e_interr);
4058 break;
4059 }
4060 }
4061
4062 if (close(bfd) < 0 && errmsg == NULL)
4063 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
4064 if (write_info.bw_len < 0)
4065 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
4066#ifdef UNIX
4067 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
4068#endif
4069#ifdef HAVE_ACL
4070 mch_set_acl(backup, acl);
4071#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004072#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004073 mch_copy_sec(fname, backup);
4074#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004075 break;
4076 }
4077 }
4078 }
4079 nobackup:
4080 close(fd); /* ignore errors for closing read file */
4081 vim_free(copybuf);
4082
4083 if (backup == NULL && errmsg == NULL)
4084 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
4085 /* ignore errors when forceit is TRUE */
4086 if ((some_error || errmsg != NULL) && !forceit)
4087 {
4088 retval = FAIL;
4089 goto fail;
4090 }
4091 errmsg = NULL;
4092 }
4093 else
4094 {
4095 char_u *dirp;
4096 char_u *p;
4097 char_u *rootname;
4098
4099 /*
4100 * Make a backup by renaming the original file.
4101 */
4102 /*
4103 * If 'cpoptions' includes the "W" flag, we don't want to
4104 * overwrite a read-only file. But rename may be possible
4105 * anyway, thus we need an extra check here.
4106 */
4107 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
4108 {
4109 errnum = (char_u *)"E504: ";
4110 errmsg = (char_u *)_(err_readonly);
4111 goto fail;
4112 }
4113
4114 /*
4115 *
4116 * Form the backup file name - change path/fo.o.h to
4117 * path/fo.o.h.bak Try all directories in 'backupdir', first one
4118 * that works is used.
4119 */
4120 dirp = p_bdir;
4121 while (*dirp)
4122 {
4123 /*
4124 * Isolate one directory name and make the backup file name.
4125 */
4126 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
4127 rootname = get_file_in_dir(fname, IObuff);
4128 if (rootname == NULL)
4129 backup = NULL;
4130 else
4131 {
4132 backup = buf_modname(
4133#ifdef SHORT_FNAME
4134 TRUE,
4135#else
4136 (buf->b_p_sn || buf->b_shortname),
4137#endif
4138 rootname, backup_ext, FALSE);
4139 vim_free(rootname);
4140 }
4141
4142 if (backup != NULL)
4143 {
4144 /*
4145 * If we are not going to keep the backup file, don't
4146 * delete an existing one, try to use another name.
4147 * Change one character, just before the extension.
4148 */
4149 if (!p_bk && mch_getperm(backup) >= 0)
4150 {
4151 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
4152 if (p < backup) /* empty file name ??? */
4153 p = backup;
4154 *p = 'z';
4155 while (*p > 'a' && mch_getperm(backup) >= 0)
4156 --*p;
4157 /* They all exist??? Must be something wrong! */
4158 if (*p == 'a')
4159 {
4160 vim_free(backup);
4161 backup = NULL;
4162 }
4163 }
4164 }
4165 if (backup != NULL)
4166 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00004168 * Delete any existing backup and move the current version
4169 * to the backup. For safety, we don't remove the backup
4170 * until the write has finished successfully. And if the
4171 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004172 */
4173 /*
4174 * If the renaming of the original file to the backup file
4175 * works, quit here.
4176 */
4177 if (vim_rename(fname, backup) == 0)
4178 break;
4179
4180 vim_free(backup); /* don't do the rename below */
4181 backup = NULL;
4182 }
4183 }
4184 if (backup == NULL && !forceit)
4185 {
4186 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
4187 goto fail;
4188 }
4189 }
4190 }
4191
4192#if defined(UNIX) && !defined(ARCHIE)
4193 /* When using ":w!" and the file was read-only: make it writable */
4194 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
4195 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
4196 {
4197 perm |= 0200;
4198 (void)mch_setperm(fname, perm);
4199 made_writable = TRUE;
4200 }
4201#endif
4202
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004203 /* When using ":w!" and writing to the current file, 'readonly' makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00004204 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
4205 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004206 {
4207 buf->b_p_ro = FALSE;
4208#ifdef FEAT_TITLE
4209 need_maketitle = TRUE; /* set window title later */
4210#endif
4211#ifdef FEAT_WINDOWS
4212 status_redraw_all(); /* redraw status lines later */
4213#endif
4214 }
4215
4216 if (end > buf->b_ml.ml_line_count)
4217 end = buf->b_ml.ml_line_count;
4218 if (buf->b_ml.ml_flags & ML_EMPTY)
4219 start = end + 1;
4220
4221 /*
4222 * If the original file is being overwritten, there is a small chance that
4223 * we crash in the middle of writing. Therefore the file is preserved now.
4224 * This makes all block numbers positive so that recovery does not need
4225 * the original file.
4226 * Don't do this if there is a backup file and we are exiting.
4227 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004228 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00004229 && !(exiting && backup != NULL))
4230 {
4231 ml_preserve(buf, FALSE);
4232 if (got_int)
4233 {
4234 errmsg = (char_u *)_(e_interr);
4235 goto restore_backup;
4236 }
4237 }
4238
4239#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4240 /*
4241 * Before risking to lose the original file verify if there's
4242 * a resource fork to preserve, and if cannot be done warn
4243 * the users. This happens when overwriting without backups.
4244 */
4245 if (backup == NULL && overwriting && !append)
4246 if (mch_has_resource_fork(fname))
4247 {
4248 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
4249 goto restore_backup;
4250 }
4251#endif
4252
4253#ifdef VMS
4254 vms_remove_version(fname); /* remove version */
4255#endif
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00004256 /* Default: write the file directly. May write to a temp file for
Bram Moolenaar071d4272004-06-13 20:20:40 +00004257 * multi-byte conversion. */
4258 wfname = fname;
4259
4260#ifdef FEAT_MBYTE
4261 /* Check for forced 'fileencoding' from "++opt=val" argument. */
4262 if (eap != NULL && eap->force_enc != 0)
4263 {
4264 fenc = eap->cmd + eap->force_enc;
4265 fenc = enc_canonize(fenc);
4266 fenc_tofree = fenc;
4267 }
4268 else
4269 fenc = buf->b_p_fenc;
4270
4271 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004272 * Check if the file needs to be converted.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004273 */
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004274 converted = need_conversion(fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004275
4276 /*
4277 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
4278 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
4279 * Prepare the flags for it and allocate bw_conv_buf when needed.
4280 */
4281 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
4282 {
4283 wb_flags = get_fio_flags(fenc);
4284 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
4285 {
4286 /* Need to allocate a buffer to translate into. */
4287 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
4288 write_info.bw_conv_buflen = bufsize * 2;
4289 else /* FIO_UCS4 */
4290 write_info.bw_conv_buflen = bufsize * 4;
4291 write_info.bw_conv_buf
4292 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4293 if (write_info.bw_conv_buf == NULL)
4294 end = 0;
4295 }
4296 }
4297
4298# ifdef WIN3264
4299 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
4300 {
4301 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
4302 write_info.bw_conv_buflen = bufsize * 4;
4303 write_info.bw_conv_buf
4304 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4305 if (write_info.bw_conv_buf == NULL)
4306 end = 0;
4307 }
4308# endif
4309
4310# ifdef MACOS_X
4311 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
4312 {
4313 write_info.bw_conv_buflen = bufsize * 3;
4314 write_info.bw_conv_buf
4315 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4316 if (write_info.bw_conv_buf == NULL)
4317 end = 0;
4318 }
4319# endif
4320
4321# if defined(FEAT_EVAL) || defined(USE_ICONV)
4322 if (converted && wb_flags == 0)
4323 {
4324# ifdef USE_ICONV
4325 /*
4326 * Use iconv() conversion when conversion is needed and it's not done
4327 * internally.
4328 */
4329 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
4330 enc_utf8 ? (char_u *)"utf-8" : p_enc);
4331 if (write_info.bw_iconv_fd != (iconv_t)-1)
4332 {
4333 /* We're going to use iconv(), allocate a buffer to convert in. */
4334 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
4335 write_info.bw_conv_buf
4336 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4337 if (write_info.bw_conv_buf == NULL)
4338 end = 0;
4339 write_info.bw_first = TRUE;
4340 }
4341# ifdef FEAT_EVAL
4342 else
4343# endif
4344# endif
4345
4346# ifdef FEAT_EVAL
4347 /*
4348 * When the file needs to be converted with 'charconvert' after
4349 * writing, write to a temp file instead and let the conversion
4350 * overwrite the original file.
4351 */
4352 if (*p_ccv != NUL)
4353 {
4354 wfname = vim_tempname('w');
4355 if (wfname == NULL) /* Can't write without a tempfile! */
4356 {
4357 errmsg = (char_u *)_("E214: Can't find temp file for writing");
4358 goto restore_backup;
4359 }
4360 }
4361# endif
4362 }
4363# endif
4364 if (converted && wb_flags == 0
4365# ifdef USE_ICONV
4366 && write_info.bw_iconv_fd == (iconv_t)-1
4367# endif
4368# ifdef FEAT_EVAL
4369 && wfname == fname
4370# endif
4371 )
4372 {
4373 if (!forceit)
4374 {
4375 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
4376 goto restore_backup;
4377 }
4378 notconverted = TRUE;
4379 }
4380#endif
4381
4382 /*
4383 * Open the file "wfname" for writing.
4384 * We may try to open the file twice: If we can't write to the
4385 * file and forceit is TRUE we delete the existing file and try to create
4386 * a new one. If this still fails we may have lost the original file!
4387 * (this may happen when the user reached his quotum for number of files).
4388 * Appending will fail if the file does not exist and forceit is FALSE.
4389 */
4390 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
4391 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
4392 : (O_CREAT | O_TRUNC))
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004393 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004394 {
4395 /*
4396 * A forced write will try to create a new file if the old one is
4397 * still readonly. This may also happen when the directory is
4398 * read-only. In that case the mch_remove() will fail.
4399 */
4400 if (errmsg == NULL)
4401 {
4402#ifdef UNIX
4403 struct stat st;
4404
4405 /* Don't delete the file when it's a hard or symbolic link. */
4406 if ((!newfile && st_old.st_nlink > 1)
4407 || (mch_lstat((char *)fname, &st) == 0
4408 && (st.st_dev != st_old.st_dev
4409 || st.st_ino != st_old.st_ino)))
4410 errmsg = (char_u *)_("E166: Can't open linked file for writing");
4411 else
4412#endif
4413 {
4414 errmsg = (char_u *)_("E212: Can't open file for writing");
4415 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
4416 && perm >= 0)
4417 {
4418#ifdef UNIX
4419 /* we write to the file, thus it should be marked
4420 writable after all */
4421 if (!(perm & 0200))
4422 made_writable = TRUE;
4423 perm |= 0200;
4424 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
4425 perm &= 0777;
4426#endif
4427 if (!append) /* don't remove when appending */
4428 mch_remove(wfname);
4429 continue;
4430 }
4431 }
4432 }
4433
4434restore_backup:
4435 {
4436 struct stat st;
4437
4438 /*
4439 * If we failed to open the file, we don't need a backup. Throw it
4440 * away. If we moved or removed the original file try to put the
4441 * backup in its place.
4442 */
4443 if (backup != NULL && wfname == fname)
4444 {
4445 if (backup_copy)
4446 {
4447 /*
4448 * There is a small chance that we removed the original,
4449 * try to move the copy in its place.
4450 * This may not work if the vim_rename() fails.
4451 * In that case we leave the copy around.
4452 */
4453 /* If file does not exist, put the copy in its place */
4454 if (mch_stat((char *)fname, &st) < 0)
4455 vim_rename(backup, fname);
4456 /* if original file does exist throw away the copy */
4457 if (mch_stat((char *)fname, &st) >= 0)
4458 mch_remove(backup);
4459 }
4460 else
4461 {
4462 /* try to put the original file back */
4463 vim_rename(backup, fname);
4464 }
4465 }
4466
4467 /* if original file no longer exists give an extra warning */
4468 if (!newfile && mch_stat((char *)fname, &st) < 0)
4469 end = 0;
4470 }
4471
4472#ifdef FEAT_MBYTE
4473 if (wfname != fname)
4474 vim_free(wfname);
4475#endif
4476 goto fail;
4477 }
4478 errmsg = NULL;
4479
4480#if defined(MACOS_CLASSIC) || defined(WIN3264)
4481 /* TODO: Is it need for MACOS_X? (Dany) */
4482 /*
4483 * On macintosh copy the original files attributes (i.e. the backup)
Bram Moolenaar7263a772007-05-10 17:35:54 +00004484 * This is done in order to preserve the resource fork and the
4485 * Finder attribute (label, comments, custom icons, file creator)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486 */
4487 if (backup != NULL && overwriting && !append)
4488 {
4489 if (backup_copy)
4490 (void)mch_copy_file_attribute(wfname, backup);
4491 else
4492 (void)mch_copy_file_attribute(backup, wfname);
4493 }
4494
4495 if (!overwriting && !append)
4496 {
4497 if (buf->b_ffname != NULL)
4498 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
Bram Moolenaar7263a772007-05-10 17:35:54 +00004499 /* Should copy resource fork */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004500 }
4501#endif
4502
4503 write_info.bw_fd = fd;
4504
4505#ifdef FEAT_CRYPT
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004506 if (*buf->b_p_key != NUL && !filtering)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004507 {
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02004508 char_u *header;
4509 int header_len;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02004510
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02004511 header = prepare_crypt_write(buf, &header_len);
4512 if (header == NULL)
4513 end = 0;
Bram Moolenaar40e6a712010-05-16 22:32:54 +02004514 else
4515 {
Bram Moolenaara3ff49f2010-05-30 22:48:02 +02004516 /* Write magic number, so that Vim knows that this file is
4517 * encrypted when reading it again. This also undergoes utf-8 to
4518 * ucs-2/4 conversion when needed. */
4519 write_info.bw_buf = header;
4520 write_info.bw_len = header_len;
4521 write_info.bw_flags = FIO_NOCONVERT;
4522 if (buf_write_bytes(&write_info) == FAIL)
4523 end = 0;
4524 wb_flags |= FIO_ENCRYPTED;
4525 vim_free(header);
Bram Moolenaar40e6a712010-05-16 22:32:54 +02004526 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004527 }
4528#endif
4529
4530 write_info.bw_buf = buffer;
4531 nchars = 0;
4532
4533 /* use "++bin", "++nobin" or 'binary' */
4534 if (eap != NULL && eap->force_bin != 0)
4535 write_bin = (eap->force_bin == FORCE_BIN);
4536 else
4537 write_bin = buf->b_p_bin;
4538
4539#ifdef FEAT_MBYTE
4540 /*
4541 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004542 * Skip it when appending and the file already existed, the BOM only makes
4543 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004544 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004545 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004546 {
4547 write_info.bw_len = make_bom(buffer, fenc);
4548 if (write_info.bw_len > 0)
4549 {
4550 /* don't convert, do encryption */
4551 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4552 if (buf_write_bytes(&write_info) == FAIL)
4553 end = 0;
4554 else
4555 nchars += write_info.bw_len;
4556 }
4557 }
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004558 write_info.bw_start_lnum = start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004559#endif
4560
Bram Moolenaar55debbe2010-05-23 23:34:36 +02004561#ifdef FEAT_PERSISTENT_UNDO
4562 write_undo_file = (buf->b_p_udf && overwriting && !append
4563 && !filtering && reset_changed);
4564 if (write_undo_file)
4565 /* Prepare for computing the hash value of the text. */
4566 sha256_start(&sha_ctx);
4567#endif
4568
Bram Moolenaar071d4272004-06-13 20:20:40 +00004569 write_info.bw_len = bufsize;
4570#ifdef HAS_BW_FLAGS
4571 write_info.bw_flags = wb_flags;
4572#endif
4573 fileformat = get_fileformat_force(buf, eap);
4574 s = buffer;
4575 len = 0;
4576 for (lnum = start; lnum <= end; ++lnum)
4577 {
4578 /*
4579 * The next while loop is done once for each character written.
4580 * Keep it fast!
4581 */
4582 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
Bram Moolenaar55debbe2010-05-23 23:34:36 +02004583#ifdef FEAT_PERSISTENT_UNDO
4584 if (write_undo_file)
Bram Moolenaar442b4222010-05-24 21:34:22 +02004585 sha256_update(&sha_ctx, ptr + 1, (UINT32_T)(STRLEN(ptr + 1) + 1));
Bram Moolenaar55debbe2010-05-23 23:34:36 +02004586#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004587 while ((c = *++ptr) != NUL)
4588 {
4589 if (c == NL)
4590 *s = NUL; /* replace newlines with NULs */
4591 else if (c == CAR && fileformat == EOL_MAC)
4592 *s = NL; /* Mac: replace CRs with NLs */
4593 else
4594 *s = c;
4595 ++s;
4596 if (++len != bufsize)
4597 continue;
4598 if (buf_write_bytes(&write_info) == FAIL)
4599 {
4600 end = 0; /* write error: break loop */
4601 break;
4602 }
4603 nchars += bufsize;
4604 s = buffer;
4605 len = 0;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004606#ifdef FEAT_MBYTE
4607 write_info.bw_start_lnum = lnum;
4608#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609 }
4610 /* write failed or last line has no EOL: stop here */
4611 if (end == 0
4612 || (lnum == end
4613 && write_bin
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01004614 && (lnum == buf->b_no_eol_lnum
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
4616 {
4617 ++lnum; /* written the line, count it */
4618 no_eol = TRUE;
4619 break;
4620 }
4621 if (fileformat == EOL_UNIX)
4622 *s++ = NL;
4623 else
4624 {
4625 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4626 if (fileformat == EOL_DOS) /* write CR-NL */
4627 {
4628 if (++len == bufsize)
4629 {
4630 if (buf_write_bytes(&write_info) == FAIL)
4631 {
4632 end = 0; /* write error: break loop */
4633 break;
4634 }
4635 nchars += bufsize;
4636 s = buffer;
4637 len = 0;
4638 }
4639 *s++ = NL;
4640 }
4641 }
4642 if (++len == bufsize && end)
4643 {
4644 if (buf_write_bytes(&write_info) == FAIL)
4645 {
4646 end = 0; /* write error: break loop */
4647 break;
4648 }
4649 nchars += bufsize;
4650 s = buffer;
4651 len = 0;
4652
4653 ui_breakcheck();
4654 if (got_int)
4655 {
4656 end = 0; /* Interrupted, break loop */
4657 break;
4658 }
4659 }
4660#ifdef VMS
4661 /*
4662 * On VMS there is a problem: newlines get added when writing blocks
4663 * at a time. Fix it by writing a line at a time.
4664 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004665 * Explanation: VAX/DECC RTL insists that records in some RMS
4666 * structures end with a newline (carriage return) character, and if
4667 * they don't it adds one.
4668 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004669 */
Bram Moolenaarb52e2602007-10-29 21:38:54 +00004670 if (buf->b_fab_rfm == FAB$C_VFC
4671 || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004673 int b2write;
4674
4675 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4676 ? MIN(4096, bufsize)
4677 : MIN(buf->b_fab_mrs, bufsize));
4678
4679 b2write = len;
4680 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004681 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004682 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4683 if (buf_write_bytes(&write_info) == FAIL)
4684 {
4685 end = 0;
4686 break;
4687 }
4688 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004689 }
4690 write_info.bw_len = bufsize;
4691 nchars += len;
4692 s = buffer;
4693 len = 0;
4694 }
4695#endif
4696 }
4697 if (len > 0 && end > 0)
4698 {
4699 write_info.bw_len = len;
4700 if (buf_write_bytes(&write_info) == FAIL)
4701 end = 0; /* write error */
4702 nchars += len;
4703 }
4704
4705#if defined(UNIX) && defined(HAVE_FSYNC)
4706 /* On many journalling file systems there is a bug that causes both the
4707 * original and the backup file to be lost when halting the system right
4708 * after writing the file. That's because only the meta-data is
4709 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004710 * been written to disk and we don't lose it.
4711 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004712 * (could be a pipe).
4713 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
4714 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004715 {
4716 errmsg = (char_u *)_("E667: Fsync failed");
4717 end = 0;
4718 }
4719#endif
4720
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02004721#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004722 /* Probably need to set the security context. */
4723 if (!backup_copy)
4724 mch_copy_sec(backup, wfname);
4725#endif
4726
Bram Moolenaara5792f52005-11-23 21:25:05 +00004727#ifdef UNIX
4728 /* When creating a new file, set its owner/group to that of the original
4729 * file. Get the new device and inode number. */
4730 if (backup != NULL && !backup_copy)
4731 {
4732# ifdef HAVE_FCHOWN
4733 struct stat st;
4734
4735 /* don't change the owner when it's already OK, some systems remove
4736 * permission or ACL stuff */
4737 if (mch_stat((char *)wfname, &st) < 0
4738 || st.st_uid != st_old.st_uid
4739 || st.st_gid != st_old.st_gid)
4740 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004741 ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004742 if (perm >= 0) /* set permission again, may have changed */
4743 (void)mch_setperm(wfname, perm);
4744 }
4745# endif
4746 buf_setino(buf);
4747 }
Bram Moolenaarf1726cc2009-05-13 18:48:16 +00004748 else if (!buf->b_dev_valid)
Bram Moolenaar8fa04452005-12-23 22:13:51 +00004749 /* Set the inode when creating a new file. */
4750 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004751#endif
4752
Bram Moolenaar071d4272004-06-13 20:20:40 +00004753 if (close(fd) != 0)
4754 {
4755 errmsg = (char_u *)_("E512: Close failed");
4756 end = 0;
4757 }
4758
4759#ifdef UNIX
4760 if (made_writable)
4761 perm &= ~0200; /* reset 'w' bit for security reasons */
4762#endif
4763 if (perm >= 0) /* set perm. of new file same as old file */
4764 (void)mch_setperm(wfname, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004765#ifdef HAVE_ACL
4766 /* Probably need to set the ACL before changing the user (can't set the
4767 * ACL on a file the user doesn't own). */
4768 if (!backup_copy)
4769 mch_set_acl(wfname, acl);
4770#endif
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004771#ifdef FEAT_CRYPT
Bram Moolenaar4cf35c22011-02-25 16:52:17 +01004772 crypt_method_used = use_crypt_method;
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02004773 if (wb_flags & FIO_ENCRYPTED)
4774 crypt_pop_state();
4775#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776
Bram Moolenaar071d4272004-06-13 20:20:40 +00004777
4778#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4779 if (wfname != fname)
4780 {
4781 /*
4782 * The file was written to a temp file, now it needs to be converted
4783 * with 'charconvert' to (overwrite) the output file.
4784 */
4785 if (end != 0)
4786 {
4787 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4788 wfname, fname) == FAIL)
4789 {
4790 write_info.bw_conv_error = TRUE;
4791 end = 0;
4792 }
4793 }
4794 mch_remove(wfname);
4795 vim_free(wfname);
4796 }
4797#endif
4798
4799 if (end == 0)
4800 {
4801 if (errmsg == NULL)
4802 {
4803#ifdef FEAT_MBYTE
4804 if (write_info.bw_conv_error)
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004805 {
4806 if (write_info.bw_conv_error_lnum == 0)
4807 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
4808 else
4809 {
4810 errmsg_allocated = TRUE;
4811 errmsg = alloc(300);
4812 vim_snprintf((char *)errmsg, 300, _("E513: write error, conversion failed in line %ld (make 'fenc' empty to override)"),
4813 (long)write_info.bw_conv_error_lnum);
4814 }
4815 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816 else
4817#endif
4818 if (got_int)
4819 errmsg = (char_u *)_(e_interr);
4820 else
4821 errmsg = (char_u *)_("E514: write error (file system full?)");
4822 }
4823
4824 /*
4825 * If we have a backup file, try to put it in place of the new file,
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004826 * because the new file is probably corrupt. This avoids losing the
Bram Moolenaar071d4272004-06-13 20:20:40 +00004827 * original file when trying to make a backup when writing the file a
4828 * second time.
4829 * When "backup_copy" is set we need to copy the backup over the new
4830 * file. Otherwise rename the backup file.
4831 * If this is OK, don't give the extra warning message.
4832 */
4833 if (backup != NULL)
4834 {
4835 if (backup_copy)
4836 {
4837 /* This may take a while, if we were interrupted let the user
4838 * know we got the message. */
4839 if (got_int)
4840 {
4841 MSG(_(e_interr));
4842 out_flush();
4843 }
4844 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4845 {
4846 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004847 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4848 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004849 {
4850 /* copy the file. */
4851 write_info.bw_buf = smallbuf;
4852#ifdef HAS_BW_FLAGS
4853 write_info.bw_flags = FIO_NOCONVERT;
4854#endif
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004855 while ((write_info.bw_len = read_eintr(fd, smallbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856 SMBUFSIZE)) > 0)
4857 if (buf_write_bytes(&write_info) == FAIL)
4858 break;
4859
4860 if (close(write_info.bw_fd) >= 0
4861 && write_info.bw_len == 0)
4862 end = 1; /* success */
4863 }
4864 close(fd); /* ignore errors for closing read file */
4865 }
4866 }
4867 else
4868 {
4869 if (vim_rename(backup, fname) == 0)
4870 end = 1;
4871 }
4872 }
4873 goto fail;
4874 }
4875
4876 lnum -= start; /* compute number of written lines */
4877 --no_wait_return; /* may wait for return now */
4878
4879#if !(defined(UNIX) || defined(VMS))
4880 fname = sfname; /* use shortname now, for the messages */
4881#endif
4882 if (!filtering)
4883 {
4884 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4885 c = FALSE;
4886#ifdef FEAT_MBYTE
4887 if (write_info.bw_conv_error)
4888 {
4889 STRCAT(IObuff, _(" CONVERSION ERROR"));
4890 c = TRUE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004891 if (write_info.bw_conv_error_lnum != 0)
Bram Moolenaara800b422010-06-27 01:15:55 +02004892 vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %ld;"),
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004893 (long)write_info.bw_conv_error_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004894 }
4895 else if (notconverted)
4896 {
4897 STRCAT(IObuff, _("[NOT converted]"));
4898 c = TRUE;
4899 }
4900 else if (converted)
4901 {
4902 STRCAT(IObuff, _("[converted]"));
4903 c = TRUE;
4904 }
4905#endif
4906 if (device)
4907 {
4908 STRCAT(IObuff, _("[Device]"));
4909 c = TRUE;
4910 }
4911 else if (newfile)
4912 {
4913 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4914 c = TRUE;
4915 }
4916 if (no_eol)
4917 {
4918 msg_add_eol();
4919 c = TRUE;
4920 }
4921 /* may add [unix/dos/mac] */
4922 if (msg_add_fileformat(fileformat))
4923 c = TRUE;
4924#ifdef FEAT_CRYPT
4925 if (wb_flags & FIO_ENCRYPTED)
4926 {
Bram Moolenaar4cf35c22011-02-25 16:52:17 +01004927 if (crypt_method_used == 1)
4928 STRCAT(IObuff, _("[blowfish]"));
4929 else
4930 STRCAT(IObuff, _("[crypted]"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004931 c = TRUE;
4932 }
4933#endif
4934 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4935 if (!shortmess(SHM_WRITE))
4936 {
4937 if (append)
4938 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4939 else
4940 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4941 }
4942
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00004943 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004944 }
4945
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004946 /* When written everything correctly: reset 'modified'. Unless not
4947 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00004948 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949#ifdef FEAT_MBYTE
4950 && !write_info.bw_conv_error
4951#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004952 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4953 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004954 {
4955 unchanged(buf, TRUE);
4956 u_unchanged(buf);
Bram Moolenaar730cde92010-06-27 05:18:54 +02004957 u_update_save_nr(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004958 }
4959
4960 /*
4961 * If written to the current file, update the timestamp of the swap file
4962 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4963 */
4964 if (overwriting)
4965 {
4966 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00004967 if (append)
4968 buf->b_flags &= ~BF_NEW;
4969 else
4970 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004971 }
4972
4973 /*
4974 * If we kept a backup until now, and we are in patch mode, then we make
4975 * the backup file our 'original' file.
4976 */
4977 if (*p_pm && dobackup)
4978 {
4979 char *org = (char *)buf_modname(
4980#ifdef SHORT_FNAME
4981 TRUE,
4982#else
4983 (buf->b_p_sn || buf->b_shortname),
4984#endif
4985 fname, p_pm, FALSE);
4986
4987 if (backup != NULL)
4988 {
4989 struct stat st;
4990
4991 /*
4992 * If the original file does not exist yet
4993 * the current backup file becomes the original file
4994 */
4995 if (org == NULL)
4996 EMSG(_("E205: Patchmode: can't save original file"));
4997 else if (mch_stat(org, &st) < 0)
4998 {
4999 vim_rename(backup, (char_u *)org);
5000 vim_free(backup); /* don't delete the file */
5001 backup = NULL;
5002#ifdef UNIX
5003 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
5004#endif
5005 }
5006 }
5007 /*
5008 * If there is no backup file, remember that a (new) file was
5009 * created.
5010 */
5011 else
5012 {
5013 int empty_fd;
5014
5015 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00005016 || (empty_fd = mch_open(org,
5017 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00005018 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 EMSG(_("E206: patchmode: can't touch empty original file"));
5020 else
5021 close(empty_fd);
5022 }
5023 if (org != NULL)
5024 {
5025 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
5026 vim_free(org);
5027 }
5028 }
5029
5030 /*
5031 * Remove the backup unless 'backup' option is set
5032 */
5033 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
5034 EMSG(_("E207: Can't delete backup file"));
5035
5036#ifdef FEAT_SUN_WORKSHOP
5037 if (usingSunWorkShop)
5038 workshop_file_saved((char *) ffname);
5039#endif
5040
5041 goto nofail;
5042
5043 /*
5044 * Finish up. We get here either after failure or success.
5045 */
5046fail:
5047 --no_wait_return; /* may wait for return now */
5048nofail:
5049
5050 /* Done saving, we accept changed buffer warnings again */
5051 buf->b_saving = FALSE;
5052
5053 vim_free(backup);
5054 if (buffer != smallbuf)
5055 vim_free(buffer);
5056#ifdef FEAT_MBYTE
5057 vim_free(fenc_tofree);
5058 vim_free(write_info.bw_conv_buf);
5059# ifdef USE_ICONV
5060 if (write_info.bw_iconv_fd != (iconv_t)-1)
5061 {
5062 iconv_close(write_info.bw_iconv_fd);
5063 write_info.bw_iconv_fd = (iconv_t)-1;
5064 }
5065# endif
5066#endif
5067#ifdef HAVE_ACL
5068 mch_free_acl(acl);
5069#endif
5070
5071 if (errmsg != NULL)
5072 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005073 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005074
5075 attr = hl_attr(HLF_E); /* set highlight for error messages */
5076 msg_add_fname(buf,
5077#ifndef UNIX
5078 sfname
5079#else
5080 fname
5081#endif
5082 ); /* put file name in IObuff with quotes */
5083 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
5084 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
5085 /* If the error message has the form "is ...", put the error number in
5086 * front of the file name. */
5087 if (errnum != NULL)
5088 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00005089 STRMOVE(IObuff + numlen, IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005090 mch_memmove(IObuff, errnum, (size_t)numlen);
5091 }
5092 STRCAT(IObuff, errmsg);
5093 emsg(IObuff);
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005094 if (errmsg_allocated)
5095 vim_free(errmsg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005096
5097 retval = FAIL;
5098 if (end == 0)
5099 {
5100 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
5101 attr | MSG_HIST);
5102 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
5103 attr | MSG_HIST);
5104
5105 /* Update the timestamp to avoid an "overwrite changed file"
5106 * prompt when writing again. */
5107 if (mch_stat((char *)fname, &st_old) >= 0)
5108 {
5109 buf_store_time(buf, &st_old, fname);
5110 buf->b_mtime_read = buf->b_mtime;
5111 }
5112 }
5113 }
5114 msg_scroll = msg_save;
5115
Bram Moolenaar55debbe2010-05-23 23:34:36 +02005116#ifdef FEAT_PERSISTENT_UNDO
5117 /*
5118 * When writing the whole file and 'undofile' is set, also write the undo
5119 * file.
5120 */
5121 if (retval == OK && write_undo_file)
5122 {
5123 char_u hash[UNDO_HASH_SIZE];
5124
5125 sha256_finish(&sha_ctx, hash);
5126 u_write_undo(NULL, FALSE, buf, hash);
5127 }
5128#endif
5129
Bram Moolenaar071d4272004-06-13 20:20:40 +00005130#ifdef FEAT_AUTOCMD
5131#ifdef FEAT_EVAL
5132 if (!should_abort(retval))
5133#else
5134 if (!got_int)
5135#endif
5136 {
5137 aco_save_T aco;
5138
Bram Moolenaar68a33fc2012-04-25 16:50:48 +02005139 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
5140
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141 /*
5142 * Apply POST autocommands.
5143 * Careful: The autocommands may call buf_write() recursively!
5144 */
5145 aucmd_prepbuf(&aco, buf);
5146
5147 if (append)
5148 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
5149 FALSE, curbuf, eap);
5150 else if (filtering)
5151 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
5152 FALSE, curbuf, eap);
5153 else if (reset_changed && whole)
5154 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
5155 FALSE, curbuf, eap);
5156 else
5157 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
5158 FALSE, curbuf, eap);
5159
5160 /* restore curwin/curbuf and a few other things */
5161 aucmd_restbuf(&aco);
5162
5163#ifdef FEAT_EVAL
5164 if (aborting()) /* autocmds may abort script processing */
5165 retval = FALSE;
5166#endif
5167 }
5168#endif
5169
5170 got_int |= prev_got_int;
5171
5172#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
5173 /* Update machine specific information. */
5174 mch_post_buffer_write(buf);
5175#endif
5176 return retval;
5177}
5178
5179/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005180 * Set the name of the current buffer. Use when the buffer doesn't have a
5181 * name and a ":r" or ":w" command with a file name is used.
5182 */
5183 static int
5184set_rw_fname(fname, sfname)
5185 char_u *fname;
5186 char_u *sfname;
5187{
5188#ifdef FEAT_AUTOCMD
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005189 buf_T *buf = curbuf;
5190
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005191 /* It's like the unnamed buffer is deleted.... */
5192 if (curbuf->b_p_bl)
5193 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
5194 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
5195# ifdef FEAT_EVAL
5196 if (aborting()) /* autocmds may abort script processing */
5197 return FAIL;
5198# endif
Bram Moolenaar8b38e242009-06-16 13:35:20 +00005199 if (curbuf != buf)
5200 {
5201 /* We are in another buffer now, don't do the renaming. */
5202 EMSG(_(e_auchangedbuf));
5203 return FAIL;
5204 }
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005205#endif
5206
5207 if (setfname(curbuf, fname, sfname, FALSE) == OK)
5208 curbuf->b_flags |= BF_NOTEDITED;
5209
5210#ifdef FEAT_AUTOCMD
5211 /* ....and a new named one is created */
5212 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
5213 if (curbuf->b_p_bl)
5214 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
5215# ifdef FEAT_EVAL
5216 if (aborting()) /* autocmds may abort script processing */
5217 return FAIL;
5218# endif
5219
5220 /* Do filetype detection now if 'filetype' is empty. */
5221 if (*curbuf->b_p_ft == NUL)
5222 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005223 if (au_has_group((char_u *)"filetypedetect"))
Bram Moolenaar70836c82006-02-20 21:28:49 +00005224 (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE);
Bram Moolenaara3227e22006-03-08 21:32:40 +00005225 do_modelines(0);
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00005226 }
5227#endif
5228
5229 return OK;
5230}
5231
5232/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005233 * Put file name into IObuff with quotes.
5234 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005235 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00005236msg_add_fname(buf, fname)
5237 buf_T *buf;
5238 char_u *fname;
5239{
5240 if (fname == NULL)
5241 fname = (char_u *)"-stdin-";
5242 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
5243 IObuff[0] = '"';
5244 STRCAT(IObuff, "\" ");
5245}
5246
5247/*
5248 * Append message for text mode to IObuff.
5249 * Return TRUE if something appended.
5250 */
5251 static int
5252msg_add_fileformat(eol_type)
5253 int eol_type;
5254{
5255#ifndef USE_CRNL
5256 if (eol_type == EOL_DOS)
5257 {
5258 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
5259 return TRUE;
5260 }
5261#endif
5262#ifndef USE_CR
5263 if (eol_type == EOL_MAC)
5264 {
5265 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
5266 return TRUE;
5267 }
5268#endif
5269#if defined(USE_CRNL) || defined(USE_CR)
5270 if (eol_type == EOL_UNIX)
5271 {
5272 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
5273 return TRUE;
5274 }
5275#endif
5276 return FALSE;
5277}
5278
5279/*
5280 * Append line and character count to IObuff.
5281 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005282 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00005283msg_add_lines(insert_space, lnum, nchars)
5284 int insert_space;
5285 long lnum;
Bram Moolenaar914703b2010-05-31 21:59:46 +02005286 off_t nchars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005287{
5288 char_u *p;
5289
5290 p = IObuff + STRLEN(IObuff);
5291
5292 if (insert_space)
5293 *p++ = ' ';
5294 if (shortmess(SHM_LINES))
Bram Moolenaar914703b2010-05-31 21:59:46 +02005295 sprintf((char *)p,
5296#ifdef LONG_LONG_OFF_T
Bram Moolenaar581966e2014-02-23 22:58:17 +01005297 "%ldL, %lldC", lnum, (long long)nchars
Bram Moolenaar914703b2010-05-31 21:59:46 +02005298#else
Bram Moolenaarf9b01292010-06-12 06:45:20 +02005299 /* Explicit typecast avoids warning on Mac OS X 10.6 */
5300 "%ldL, %ldC", lnum, (long)nchars
Bram Moolenaar914703b2010-05-31 21:59:46 +02005301#endif
Bram Moolenaarf9b01292010-06-12 06:45:20 +02005302 );
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303 else
5304 {
5305 if (lnum == 1)
5306 STRCPY(p, _("1 line, "));
5307 else
5308 sprintf((char *)p, _("%ld lines, "), lnum);
5309 p += STRLEN(p);
5310 if (nchars == 1)
5311 STRCPY(p, _("1 character"));
5312 else
Bram Moolenaar914703b2010-05-31 21:59:46 +02005313 sprintf((char *)p,
5314#ifdef LONG_LONG_OFF_T
Bram Moolenaar581966e2014-02-23 22:58:17 +01005315 _("%lld characters"), (long long)nchars
Bram Moolenaar914703b2010-05-31 21:59:46 +02005316#else
Bram Moolenaarf9b01292010-06-12 06:45:20 +02005317 /* Explicit typecast avoids warning on Mac OS X 10.6 */
5318 _("%ld characters"), (long)nchars
Bram Moolenaar914703b2010-05-31 21:59:46 +02005319#endif
Bram Moolenaarf9b01292010-06-12 06:45:20 +02005320 );
Bram Moolenaar071d4272004-06-13 20:20:40 +00005321 }
5322}
5323
5324/*
5325 * Append message for missing line separator to IObuff.
5326 */
5327 static void
5328msg_add_eol()
5329{
5330 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
5331}
5332
5333/*
5334 * Check modification time of file, before writing to it.
5335 * The size isn't checked, because using a tool like "gzip" takes care of
5336 * using the same timestamp but can't set the size.
5337 */
5338 static int
5339check_mtime(buf, st)
5340 buf_T *buf;
5341 struct stat *st;
5342{
5343 if (buf->b_mtime_read != 0
5344 && time_differs((long)st->st_mtime, buf->b_mtime_read))
5345 {
5346 msg_scroll = TRUE; /* don't overwrite messages here */
5347 msg_silent = 0; /* must give this prompt */
5348 /* don't use emsg() here, don't want to flush the buffers */
5349 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
5350 hl_attr(HLF_E));
5351 if (ask_yesno((char_u *)_("Do you really want to write to it"),
5352 TRUE) == 'n')
5353 return FAIL;
5354 msg_scroll = FALSE; /* always overwrite the file message now */
5355 }
5356 return OK;
5357}
5358
5359 static int
5360time_differs(t1, t2)
5361 long t1, t2;
5362{
5363#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
5364 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
5365 * the seconds. Since the roundoff is done when flushing the inode, the
5366 * time may change unexpectedly by one second!!! */
5367 return (t1 - t2 > 1 || t2 - t1 > 1);
5368#else
5369 return (t1 != t2);
5370#endif
5371}
5372
5373/*
5374 * Call write() to write a number of bytes to the file.
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005375 * Handles encryption and 'encoding' conversion.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005376 *
5377 * Return FAIL for failure, OK otherwise.
5378 */
5379 static int
5380buf_write_bytes(ip)
5381 struct bw_info *ip;
5382{
5383 int wlen;
5384 char_u *buf = ip->bw_buf; /* data to write */
5385 int len = ip->bw_len; /* length of data */
5386#ifdef HAS_BW_FLAGS
5387 int flags = ip->bw_flags; /* extra flags */
5388#endif
5389
5390#ifdef FEAT_MBYTE
5391 /*
5392 * Skip conversion when writing the crypt magic number or the BOM.
5393 */
5394 if (!(flags & FIO_NOCONVERT))
5395 {
5396 char_u *p;
5397 unsigned c;
5398 int n;
5399
5400 if (flags & FIO_UTF8)
5401 {
5402 /*
5403 * Convert latin1 in the buffer to UTF-8 in the file.
5404 */
5405 p = ip->bw_conv_buf; /* translate to buffer */
5406 for (wlen = 0; wlen < len; ++wlen)
5407 p += utf_char2bytes(buf[wlen], p);
5408 buf = ip->bw_conv_buf;
5409 len = (int)(p - ip->bw_conv_buf);
5410 }
5411 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
5412 {
5413 /*
5414 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
5415 * Latin1 chars in the file.
5416 */
5417 if (flags & FIO_LATIN1)
5418 p = buf; /* translate in-place (can only get shorter) */
5419 else
5420 p = ip->bw_conv_buf; /* translate to buffer */
5421 for (wlen = 0; wlen < len; wlen += n)
5422 {
5423 if (wlen == 0 && ip->bw_restlen != 0)
5424 {
5425 int l;
5426
5427 /* Use remainder of previous call. Append the start of
5428 * buf[] to get a full sequence. Might still be too
5429 * short! */
5430 l = CONV_RESTLEN - ip->bw_restlen;
5431 if (l > len)
5432 l = len;
5433 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005434 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005435 if (n > ip->bw_restlen + len)
5436 {
5437 /* We have an incomplete byte sequence at the end to
5438 * be written. We can't convert it without the
5439 * remaining bytes. Keep them for the next call. */
5440 if (ip->bw_restlen + len > CONV_RESTLEN)
5441 return FAIL;
5442 ip->bw_restlen += len;
5443 break;
5444 }
5445 if (n > 1)
5446 c = utf_ptr2char(ip->bw_rest);
5447 else
5448 c = ip->bw_rest[0];
5449 if (n >= ip->bw_restlen)
5450 {
5451 n -= ip->bw_restlen;
5452 ip->bw_restlen = 0;
5453 }
5454 else
5455 {
5456 ip->bw_restlen -= n;
5457 mch_memmove(ip->bw_rest, ip->bw_rest + n,
5458 (size_t)ip->bw_restlen);
5459 n = 0;
5460 }
5461 }
5462 else
5463 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005464 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005465 if (n > len - wlen)
5466 {
5467 /* We have an incomplete byte sequence at the end to
5468 * be written. We can't convert it without the
5469 * remaining bytes. Keep them for the next call. */
5470 if (len - wlen > CONV_RESTLEN)
5471 return FAIL;
5472 ip->bw_restlen = len - wlen;
5473 mch_memmove(ip->bw_rest, buf + wlen,
5474 (size_t)ip->bw_restlen);
5475 break;
5476 }
5477 if (n > 1)
5478 c = utf_ptr2char(buf + wlen);
5479 else
5480 c = buf[wlen];
5481 }
5482
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005483 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error)
5484 {
5485 ip->bw_conv_error = TRUE;
5486 ip->bw_conv_error_lnum = ip->bw_start_lnum;
5487 }
5488 if (c == NL)
5489 ++ip->bw_start_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490 }
5491 if (flags & FIO_LATIN1)
5492 len = (int)(p - buf);
5493 else
5494 {
5495 buf = ip->bw_conv_buf;
5496 len = (int)(p - ip->bw_conv_buf);
5497 }
5498 }
5499
5500# ifdef WIN3264
5501 else if (flags & FIO_CODEPAGE)
5502 {
5503 /*
5504 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
5505 * codepage.
5506 */
5507 char_u *from;
5508 size_t fromlen;
5509 char_u *to;
5510 int u8c;
5511 BOOL bad = FALSE;
5512 int needed;
5513
5514 if (ip->bw_restlen > 0)
5515 {
5516 /* Need to concatenate the remainder of the previous call and
5517 * the bytes of the current call. Use the end of the
5518 * conversion buffer for this. */
5519 fromlen = len + ip->bw_restlen;
5520 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5521 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5522 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5523 }
5524 else
5525 {
5526 from = buf;
5527 fromlen = len;
5528 }
5529
5530 to = ip->bw_conv_buf;
5531 if (enc_utf8)
5532 {
5533 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
5534 * The buffer has been allocated to be big enough. */
5535 while (fromlen > 0)
5536 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005537 n = (int)utf_ptr2len_len(from, (int)fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005538 if (n > (int)fromlen) /* incomplete byte sequence */
5539 break;
5540 u8c = utf_ptr2char(from);
5541 *to++ = (u8c & 0xff);
5542 *to++ = (u8c >> 8);
5543 fromlen -= n;
5544 from += n;
5545 }
5546
5547 /* Copy remainder to ip->bw_rest[] to be used for the next
5548 * call. */
5549 if (fromlen > CONV_RESTLEN)
5550 {
5551 /* weird overlong sequence */
5552 ip->bw_conv_error = TRUE;
5553 return FAIL;
5554 }
5555 mch_memmove(ip->bw_rest, from, fromlen);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005556 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005557 }
5558 else
5559 {
5560 /* Convert from enc_codepage to UCS-2, to the start of the
5561 * buffer. The buffer has been allocated to be big enough. */
5562 ip->bw_restlen = 0;
5563 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005564 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005565 NULL, 0);
5566 if (needed == 0)
5567 {
5568 /* When conversion fails there may be a trailing byte. */
5569 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005570 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005571 NULL, 0);
5572 if (needed == 0)
5573 {
5574 /* Conversion doesn't work. */
5575 ip->bw_conv_error = TRUE;
5576 return FAIL;
5577 }
5578 /* Save the trailing byte for the next call. */
5579 ip->bw_rest[0] = from[fromlen - 1];
5580 ip->bw_restlen = 1;
5581 }
5582 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005583 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005584 (LPWSTR)to, needed);
5585 if (needed == 0)
5586 {
5587 /* Safety check: Conversion doesn't work. */
5588 ip->bw_conv_error = TRUE;
5589 return FAIL;
5590 }
5591 to += needed * 2;
5592 }
5593
5594 fromlen = to - ip->bw_conv_buf;
5595 buf = to;
5596# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5597 if (FIO_GET_CP(flags) == CP_UTF8)
5598 {
5599 /* Convert from UCS-2 to UTF-8, using the remainder of the
5600 * conversion buffer. Fails when out of space. */
5601 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
5602 {
5603 u8c = *from++;
5604 u8c += (*from++ << 8);
5605 to += utf_char2bytes(u8c, to);
5606 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
5607 {
5608 ip->bw_conv_error = TRUE;
5609 return FAIL;
5610 }
5611 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005612 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 }
5614 else
5615#endif
5616 {
5617 /* Convert from UCS-2 to the codepage, using the remainder of
5618 * the conversion buffer. If the conversion uses the default
5619 * character "0", the data doesn't fit in this encoding, so
5620 * fail. */
5621 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5622 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005623 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0,
5624 &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 if (bad)
5626 {
5627 ip->bw_conv_error = TRUE;
5628 return FAIL;
5629 }
5630 }
5631 }
5632# endif
5633
Bram Moolenaar56718732006-03-15 22:53:57 +00005634# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005635 else if (flags & FIO_MACROMAN)
5636 {
5637 /*
5638 * Convert UTF-8 or latin1 to Apple MacRoman.
5639 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005640 char_u *from;
5641 size_t fromlen;
5642
5643 if (ip->bw_restlen > 0)
5644 {
5645 /* Need to concatenate the remainder of the previous call and
5646 * the bytes of the current call. Use the end of the
5647 * conversion buffer for this. */
5648 fromlen = len + ip->bw_restlen;
5649 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5650 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5651 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5652 }
5653 else
5654 {
5655 from = buf;
5656 fromlen = len;
5657 }
5658
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005659 if (enc2macroman(from, fromlen,
5660 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5661 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005662 {
5663 ip->bw_conv_error = TRUE;
5664 return FAIL;
5665 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005666 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005667 }
5668# endif
5669
5670# ifdef USE_ICONV
5671 if (ip->bw_iconv_fd != (iconv_t)-1)
5672 {
5673 const char *from;
5674 size_t fromlen;
5675 char *to;
5676 size_t tolen;
5677
5678 /* Convert with iconv(). */
5679 if (ip->bw_restlen > 0)
5680 {
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005681 char *fp;
5682
Bram Moolenaar071d4272004-06-13 20:20:40 +00005683 /* Need to concatenate the remainder of the previous call and
5684 * the bytes of the current call. Use the end of the
5685 * conversion buffer for this. */
5686 fromlen = len + ip->bw_restlen;
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005687 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5688 mch_memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
5689 mch_memmove(fp + ip->bw_restlen, buf, (size_t)len);
5690 from = fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005691 tolen = ip->bw_conv_buflen - fromlen;
5692 }
5693 else
5694 {
5695 from = (const char *)buf;
5696 fromlen = len;
5697 tolen = ip->bw_conv_buflen;
5698 }
5699 to = (char *)ip->bw_conv_buf;
5700
5701 if (ip->bw_first)
5702 {
5703 size_t save_len = tolen;
5704
5705 /* output the initial shift state sequence */
5706 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5707
5708 /* There is a bug in iconv() on Linux (which appears to be
5709 * wide-spread) which sets "to" to NULL and messes up "tolen".
5710 */
5711 if (to == NULL)
5712 {
5713 to = (char *)ip->bw_conv_buf;
5714 tolen = save_len;
5715 }
5716 ip->bw_first = FALSE;
5717 }
5718
5719 /*
5720 * If iconv() has an error or there is not enough room, fail.
5721 */
5722 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5723 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5724 || fromlen > CONV_RESTLEN)
5725 {
5726 ip->bw_conv_error = TRUE;
5727 return FAIL;
5728 }
5729
5730 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5731 if (fromlen > 0)
5732 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5733 ip->bw_restlen = (int)fromlen;
5734
5735 buf = ip->bw_conv_buf;
5736 len = (int)((char_u *)to - ip->bw_conv_buf);
5737 }
5738# endif
5739 }
5740#endif /* FEAT_MBYTE */
5741
5742#ifdef FEAT_CRYPT
5743 if (flags & FIO_ENCRYPTED) /* encrypt the data */
Bram Moolenaar04c9baf2010-06-01 23:37:39 +02005744 crypt_encode(buf, len, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005745#endif
5746
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01005747 wlen = write_eintr(ip->bw_fd, buf, len);
5748 return (wlen < len) ? FAIL : OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749}
5750
5751#ifdef FEAT_MBYTE
5752/*
5753 * Convert a Unicode character to bytes.
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005754 * Return TRUE for an error, FALSE when it's OK.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005755 */
5756 static int
5757ucs2bytes(c, pp, flags)
5758 unsigned c; /* in: character */
5759 char_u **pp; /* in/out: pointer to result */
5760 int flags; /* FIO_ flags */
5761{
5762 char_u *p = *pp;
5763 int error = FALSE;
5764 int cc;
5765
5766
5767 if (flags & FIO_UCS4)
5768 {
5769 if (flags & FIO_ENDIAN_L)
5770 {
5771 *p++ = c;
5772 *p++ = (c >> 8);
5773 *p++ = (c >> 16);
5774 *p++ = (c >> 24);
5775 }
5776 else
5777 {
5778 *p++ = (c >> 24);
5779 *p++ = (c >> 16);
5780 *p++ = (c >> 8);
5781 *p++ = c;
5782 }
5783 }
5784 else if (flags & (FIO_UCS2 | FIO_UTF16))
5785 {
5786 if (c >= 0x10000)
5787 {
5788 if (flags & FIO_UTF16)
5789 {
5790 /* Make two words, ten bits of the character in each. First
5791 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5792 c -= 0x10000;
5793 if (c >= 0x100000)
5794 error = TRUE;
5795 cc = ((c >> 10) & 0x3ff) + 0xd800;
5796 if (flags & FIO_ENDIAN_L)
5797 {
5798 *p++ = cc;
5799 *p++ = ((unsigned)cc >> 8);
5800 }
5801 else
5802 {
5803 *p++ = ((unsigned)cc >> 8);
5804 *p++ = cc;
5805 }
5806 c = (c & 0x3ff) + 0xdc00;
5807 }
5808 else
5809 error = TRUE;
5810 }
5811 if (flags & FIO_ENDIAN_L)
5812 {
5813 *p++ = c;
5814 *p++ = (c >> 8);
5815 }
5816 else
5817 {
5818 *p++ = (c >> 8);
5819 *p++ = c;
5820 }
5821 }
5822 else /* Latin1 */
5823 {
5824 if (c >= 0x100)
5825 {
5826 error = TRUE;
5827 *p++ = 0xBF;
5828 }
5829 else
5830 *p++ = c;
5831 }
5832
5833 *pp = p;
5834 return error;
5835}
5836
5837/*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005838 * Return TRUE if file encoding "fenc" requires conversion from or to
5839 * 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005840 */
5841 static int
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005842need_conversion(fenc)
5843 char_u *fenc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005844{
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005845 int same_encoding;
5846 int enc_flags;
5847 int fenc_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005848
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005849 if (*fenc == NUL || STRCMP(p_enc, fenc) == 0)
Bram Moolenaar442b4222010-05-24 21:34:22 +02005850 {
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005851 same_encoding = TRUE;
Bram Moolenaar442b4222010-05-24 21:34:22 +02005852 fenc_flags = 0;
5853 }
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005854 else
5855 {
5856 /* Ignore difference between "ansi" and "latin1", "ucs-4" and
5857 * "ucs-4be", etc. */
5858 enc_flags = get_fio_flags(p_enc);
5859 fenc_flags = get_fio_flags(fenc);
5860 same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
5861 }
5862 if (same_encoding)
5863 {
5864 /* Specified encoding matches with 'encoding'. This requires
5865 * conversion when 'encoding' is Unicode but not UTF-8. */
5866 return enc_unicode != 0;
5867 }
5868
5869 /* Encodings differ. However, conversion is not needed when 'enc' is any
5870 * Unicode encoding and the file is UTF-8. */
5871 return !(enc_utf8 && fenc_flags == FIO_UTF8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005872}
5873
5874/*
5875 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5876 * internal conversion.
5877 * if "ptr" is an empty string, use 'encoding'.
5878 */
5879 static int
5880get_fio_flags(ptr)
5881 char_u *ptr;
5882{
5883 int prop;
5884
5885 if (*ptr == NUL)
5886 ptr = p_enc;
5887
5888 prop = enc_canon_props(ptr);
5889 if (prop & ENC_UNICODE)
5890 {
5891 if (prop & ENC_2BYTE)
5892 {
5893 if (prop & ENC_ENDIAN_L)
5894 return FIO_UCS2 | FIO_ENDIAN_L;
5895 return FIO_UCS2;
5896 }
5897 if (prop & ENC_4BYTE)
5898 {
5899 if (prop & ENC_ENDIAN_L)
5900 return FIO_UCS4 | FIO_ENDIAN_L;
5901 return FIO_UCS4;
5902 }
5903 if (prop & ENC_2WORD)
5904 {
5905 if (prop & ENC_ENDIAN_L)
5906 return FIO_UTF16 | FIO_ENDIAN_L;
5907 return FIO_UTF16;
5908 }
5909 return FIO_UTF8;
5910 }
5911 if (prop & ENC_LATIN1)
5912 return FIO_LATIN1;
5913 /* must be ENC_DBCS, requires iconv() */
5914 return 0;
5915}
5916
5917#ifdef WIN3264
5918/*
5919 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5920 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5921 * Used for conversion between 'encoding' and 'fileencoding'.
5922 */
5923 static int
5924get_win_fio_flags(ptr)
5925 char_u *ptr;
5926{
5927 int cp;
5928
5929 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5930 if (!enc_utf8 && enc_codepage <= 0)
5931 return 0;
5932
5933 cp = encname2codepage(ptr);
5934 if (cp == 0)
5935 {
5936# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5937 if (STRCMP(ptr, "utf-8") == 0)
5938 cp = CP_UTF8;
5939 else
5940# endif
5941 return 0;
5942 }
5943 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5944}
5945#endif
5946
5947#ifdef MACOS_X
5948/*
5949 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5950 * needed for the internal conversion to/from utf-8 or latin1.
5951 */
5952 static int
5953get_mac_fio_flags(ptr)
5954 char_u *ptr;
5955{
5956 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5957 && (enc_canon_props(ptr) & ENC_MACROMAN))
5958 return FIO_MACROMAN;
5959 return 0;
5960}
5961#endif
5962
5963/*
5964 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5965 * "size" must be at least 2.
5966 * Return the name of the encoding and set "*lenp" to the length.
5967 * Returns NULL when no BOM found.
5968 */
5969 static char_u *
5970check_for_bom(p, size, lenp, flags)
5971 char_u *p;
5972 long size;
5973 int *lenp;
5974 int flags;
5975{
5976 char *name = NULL;
5977 int len = 2;
5978
5979 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
Bram Moolenaaree0f5a62008-07-24 20:09:16 +00005980 && (flags == FIO_ALL || flags == FIO_UTF8 || flags == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981 {
5982 name = "utf-8"; /* EF BB BF */
5983 len = 3;
5984 }
5985 else if (p[0] == 0xff && p[1] == 0xfe)
5986 {
5987 if (size >= 4 && p[2] == 0 && p[3] == 0
5988 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5989 {
5990 name = "ucs-4le"; /* FF FE 00 00 */
5991 len = 4;
5992 }
Bram Moolenaar223a1892008-11-11 20:57:11 +00005993 else if (flags == (FIO_UCS2 | FIO_ENDIAN_L))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005994 name = "ucs-2le"; /* FF FE */
Bram Moolenaar223a1892008-11-11 20:57:11 +00005995 else if (flags == FIO_ALL || flags == (FIO_UTF16 | FIO_ENDIAN_L))
5996 /* utf-16le is preferred, it also works for ucs-2le text */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005997 name = "utf-16le"; /* FF FE */
5998 }
5999 else if (p[0] == 0xfe && p[1] == 0xff
6000 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
6001 {
Bram Moolenaarffd82c52008-02-20 17:15:26 +00006002 /* Default to utf-16, it works also for ucs-2 text. */
6003 if (flags == FIO_UCS2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006004 name = "ucs-2"; /* FE FF */
Bram Moolenaarffd82c52008-02-20 17:15:26 +00006005 else
6006 name = "utf-16"; /* FE FF */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006007 }
6008 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
6009 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
6010 {
6011 name = "ucs-4"; /* 00 00 FE FF */
6012 len = 4;
6013 }
6014
6015 *lenp = len;
6016 return (char_u *)name;
6017}
6018
6019/*
6020 * Generate a BOM in "buf[4]" for encoding "name".
6021 * Return the length of the BOM (zero when no BOM).
6022 */
6023 static int
6024make_bom(buf, name)
6025 char_u *buf;
6026 char_u *name;
6027{
6028 int flags;
6029 char_u *p;
6030
6031 flags = get_fio_flags(name);
6032
6033 /* Can't put a BOM in a non-Unicode file. */
6034 if (flags == FIO_LATIN1 || flags == 0)
6035 return 0;
6036
6037 if (flags == FIO_UTF8) /* UTF-8 */
6038 {
6039 buf[0] = 0xef;
6040 buf[1] = 0xbb;
6041 buf[2] = 0xbf;
6042 return 3;
6043 }
6044 p = buf;
6045 (void)ucs2bytes(0xfeff, &p, flags);
6046 return (int)(p - buf);
6047}
6048#endif
6049
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00006050#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \
Bram Moolenaara0174af2008-01-02 20:08:25 +00006051 defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006052/*
6053 * Try to find a shortname by comparing the fullname with the current
6054 * directory.
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006055 * Returns "full_path" or pointer into "full_path" if shortened.
6056 */
6057 char_u *
6058shorten_fname1(full_path)
6059 char_u *full_path;
6060{
Bram Moolenaard9462e32011-04-11 21:35:11 +02006061 char_u *dirname;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006062 char_u *p = full_path;
6063
Bram Moolenaard9462e32011-04-11 21:35:11 +02006064 dirname = alloc(MAXPATHL);
6065 if (dirname == NULL)
6066 return full_path;
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006067 if (mch_dirname(dirname, MAXPATHL) == OK)
6068 {
6069 p = shorten_fname(full_path, dirname);
6070 if (p == NULL || *p == NUL)
6071 p = full_path;
6072 }
Bram Moolenaard9462e32011-04-11 21:35:11 +02006073 vim_free(dirname);
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006074 return p;
6075}
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00006076#endif
Bram Moolenaard089d9b2007-09-30 12:02:55 +00006077
6078/*
6079 * Try to find a shortname by comparing the fullname with the current
6080 * directory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006081 * Returns NULL if not shorter name possible, pointer into "full_path"
6082 * otherwise.
6083 */
6084 char_u *
6085shorten_fname(full_path, dir_name)
6086 char_u *full_path;
6087 char_u *dir_name;
6088{
6089 int len;
6090 char_u *p;
6091
6092 if (full_path == NULL)
6093 return NULL;
6094 len = (int)STRLEN(dir_name);
6095 if (fnamencmp(dir_name, full_path, len) == 0)
6096 {
6097 p = full_path + len;
6098#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
6099 /*
6100 * MSDOS: when a file is in the root directory, dir_name will end in a
6101 * slash, since C: by itself does not define a specific dir. In this
6102 * case p may already be correct. <negri>
6103 */
6104 if (!((len > 2) && (*(p - 2) == ':')))
6105#endif
6106 {
6107 if (vim_ispathsep(*p))
6108 ++p;
6109#ifndef VMS /* the path separator is always part of the path */
6110 else
6111 p = NULL;
6112#endif
6113 }
6114 }
6115#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
6116 /*
6117 * When using a file in the current drive, remove the drive name:
6118 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
6119 * a floppy from "A:\dir" to "B:\dir".
6120 */
6121 else if (len > 3
6122 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
6123 && full_path[1] == ':'
6124 && vim_ispathsep(full_path[2]))
6125 p = full_path + 2;
6126#endif
6127 else
6128 p = NULL;
6129 return p;
6130}
6131
6132/*
6133 * Shorten filenames for all buffers.
6134 * When "force" is TRUE: Use full path from now on for files currently being
6135 * edited, both for file name and swap file name. Try to shorten the file
6136 * names a bit, if safe to do so.
6137 * When "force" is FALSE: Only try to shorten absolute file names.
6138 * For buffers that have buftype "nofile" or "scratch": never change the file
6139 * name.
6140 */
6141 void
6142shorten_fnames(force)
6143 int force;
6144{
6145 char_u dirname[MAXPATHL];
6146 buf_T *buf;
6147 char_u *p;
6148
6149 mch_dirname(dirname, MAXPATHL);
6150 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
6151 {
6152 if (buf->b_fname != NULL
6153#ifdef FEAT_QUICKFIX
6154 && !bt_nofile(buf)
6155#endif
6156 && !path_with_url(buf->b_fname)
6157 && (force
6158 || buf->b_sfname == NULL
6159 || mch_isFullName(buf->b_sfname)))
6160 {
6161 vim_free(buf->b_sfname);
6162 buf->b_sfname = NULL;
6163 p = shorten_fname(buf->b_ffname, dirname);
6164 if (p != NULL)
6165 {
6166 buf->b_sfname = vim_strsave(p);
6167 buf->b_fname = buf->b_sfname;
6168 }
6169 if (p == NULL || buf->b_fname == NULL)
6170 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006171 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006172
6173 /* Always make the swap file name a full path, a "nofile" buffer may
6174 * also have a swap file. */
6175 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006176 }
6177#ifdef FEAT_WINDOWS
6178 status_redraw_all();
Bram Moolenaar49d7bf12006-02-17 21:45:41 +00006179 redraw_tabline = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006180#endif
6181}
6182
6183#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
6184 || defined(FEAT_GUI_MSWIN) \
6185 || defined(FEAT_GUI_MAC) \
6186 || defined(PROTO)
6187/*
6188 * Shorten all filenames in "fnames[count]" by current directory.
6189 */
6190 void
6191shorten_filenames(fnames, count)
6192 char_u **fnames;
6193 int count;
6194{
6195 int i;
6196 char_u dirname[MAXPATHL];
6197 char_u *p;
6198
6199 if (fnames == NULL || count < 1)
6200 return;
6201 mch_dirname(dirname, sizeof(dirname));
6202 for (i = 0; i < count; ++i)
6203 {
6204 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
6205 {
6206 /* shorten_fname() returns pointer in given "fnames[i]". If free
6207 * "fnames[i]" first, "p" becomes invalid. So we need to copy
6208 * "p" first then free fnames[i]. */
6209 p = vim_strsave(p);
6210 vim_free(fnames[i]);
6211 fnames[i] = p;
6212 }
6213 }
6214}
6215#endif
6216
6217/*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006218 * add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
Bram Moolenaar071d4272004-06-13 20:20:40 +00006219 * fo_o_h.ext for MSDOS or when shortname option set.
6220 *
6221 * Assumed that fname is a valid name found in the filesystem we assure that
6222 * the return value is a different name and ends in 'ext'.
6223 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
6224 * characters otherwise.
6225 * Space for the returned name is allocated, must be freed later.
6226 * Returns NULL when out of memory.
6227 */
6228 char_u *
6229modname(fname, ext, prepend_dot)
6230 char_u *fname, *ext;
6231 int prepend_dot; /* may prepend a '.' to file name */
6232{
6233 return buf_modname(
6234#ifdef SHORT_FNAME
6235 TRUE,
6236#else
6237 (curbuf->b_p_sn || curbuf->b_shortname),
6238#endif
6239 fname, ext, prepend_dot);
6240}
6241
6242 char_u *
6243buf_modname(shortname, fname, ext, prepend_dot)
6244 int shortname; /* use 8.3 file name */
6245 char_u *fname, *ext;
6246 int prepend_dot; /* may prepend a '.' to file name */
6247{
6248 char_u *retval;
6249 char_u *s;
6250 char_u *e;
6251 char_u *ptr;
6252 int fnamelen, extlen;
6253
6254 extlen = (int)STRLEN(ext);
6255
6256 /*
6257 * If there is no file name we must get the name of the current directory
6258 * (we need the full path in case :cd is used).
6259 */
6260 if (fname == NULL || *fname == NUL)
6261 {
6262 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
6263 if (retval == NULL)
6264 return NULL;
6265 if (mch_dirname(retval, MAXPATHL) == FAIL ||
6266 (fnamelen = (int)STRLEN(retval)) == 0)
6267 {
6268 vim_free(retval);
6269 return NULL;
6270 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006271 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006272 {
6273 retval[fnamelen++] = PATHSEP;
6274 retval[fnamelen] = NUL;
6275 }
6276#ifndef SHORT_FNAME
6277 prepend_dot = FALSE; /* nothing to prepend a dot to */
6278#endif
6279 }
6280 else
6281 {
6282 fnamelen = (int)STRLEN(fname);
6283 retval = alloc((unsigned)(fnamelen + extlen + 3));
6284 if (retval == NULL)
6285 return NULL;
6286 STRCPY(retval, fname);
6287#ifdef VMS
6288 vms_remove_version(retval); /* we do not need versions here */
6289#endif
6290 }
6291
6292 /*
6293 * search backwards until we hit a '/', '\' or ':' replacing all '.'
6294 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
6295 * Then truncate what is after the '/', '\' or ':' to 8 characters for
6296 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
6297 */
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006298 for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006299 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006300 if (*ext == '.'
Bram Moolenaare60acc12011-05-10 16:41:25 +02006301#ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006302 && (!USE_LONG_FNAME || shortname)
Bram Moolenaare60acc12011-05-10 16:41:25 +02006303#else
6304# ifndef SHORT_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006305 && shortname
6306# endif
Bram Moolenaare60acc12011-05-10 16:41:25 +02006307#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006308 )
6309 if (*ptr == '.') /* replace '.' by '_' */
6310 *ptr = '_';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006311 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006312 {
6313 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006314 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006315 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006316 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006317
6318 /* the file name has at most BASENAMELEN characters. */
6319#ifndef SHORT_FNAME
6320 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
6321 ptr[BASENAMELEN] = '\0';
6322#endif
6323
6324 s = ptr + STRLEN(ptr);
6325
6326 /*
6327 * For 8.3 file names we may have to reduce the length.
6328 */
6329#ifdef USE_LONG_FNAME
6330 if (!USE_LONG_FNAME || shortname)
6331#else
6332# ifndef SHORT_FNAME
6333 if (shortname)
6334# endif
6335#endif
6336 {
6337 /*
6338 * If there is no file name, or the file name ends in '/', and the
6339 * extension starts with '.', put a '_' before the dot, because just
6340 * ".ext" is invalid.
6341 */
6342 if (fname == NULL || *fname == NUL
6343 || vim_ispathsep(fname[STRLEN(fname) - 1]))
6344 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006345 if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006346 *s++ = '_';
6347 }
6348 /*
6349 * If the extension starts with '.', truncate the base name at 8
6350 * characters
6351 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006352 else if (*ext == '.')
Bram Moolenaar071d4272004-06-13 20:20:40 +00006353 {
Bram Moolenaar78a15312009-05-15 19:33:18 +00006354 if ((size_t)(s - ptr) > (size_t)8)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006355 {
6356 s = ptr + 8;
6357 *s = '\0';
6358 }
6359 }
6360 /*
6361 * If the extension doesn't start with '.', and the file name
6362 * doesn't have an extension yet, append a '.'
6363 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006364 else if ((e = vim_strchr(ptr, '.')) == NULL)
6365 *s++ = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006366 /*
6367 * If the extension doesn't start with '.', and there already is an
Bram Moolenaar7263a772007-05-10 17:35:54 +00006368 * extension, it may need to be truncated
Bram Moolenaar071d4272004-06-13 20:20:40 +00006369 */
6370 else if ((int)STRLEN(e) + extlen > 4)
6371 s = e + 4 - extlen;
6372 }
6373#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
6374 /*
6375 * If there is no file name, and the extension starts with '.', put a
6376 * '_' before the dot, because just ".ext" may be invalid if it's on a
6377 * FAT partition, and on HPFS it doesn't matter.
6378 */
6379 else if ((fname == NULL || *fname == NUL) && *ext == '.')
6380 *s++ = '_';
6381#endif
6382
6383 /*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006384 * Append the extension.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006385 * ext can start with '.' and cannot exceed 3 more characters.
6386 */
6387 STRCPY(s, ext);
6388
6389#ifndef SHORT_FNAME
6390 /*
6391 * Prepend the dot.
6392 */
Bram Moolenaare60acc12011-05-10 16:41:25 +02006393 if (prepend_dot && !shortname && *(e = gettail(retval)) != '.'
Bram Moolenaar071d4272004-06-13 20:20:40 +00006394#ifdef USE_LONG_FNAME
6395 && USE_LONG_FNAME
6396#endif
6397 )
6398 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006399 STRMOVE(e + 1, e);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006400 *e = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006401 }
6402#endif
6403
6404 /*
6405 * Check that, after appending the extension, the file name is really
6406 * different.
6407 */
6408 if (fname != NULL && STRCMP(fname, retval) == 0)
6409 {
6410 /* we search for a character that can be replaced by '_' */
6411 while (--s >= ptr)
6412 {
6413 if (*s != '_')
6414 {
6415 *s = '_';
6416 break;
6417 }
6418 }
6419 if (s < ptr) /* fname was "________.<ext>", how tricky! */
6420 *ptr = 'v';
6421 }
6422 return retval;
6423}
6424
6425/*
6426 * Like fgets(), but if the file line is too long, it is truncated and the
6427 * rest of the line is thrown away. Returns TRUE for end-of-file.
6428 */
6429 int
6430vim_fgets(buf, size, fp)
6431 char_u *buf;
6432 int size;
6433 FILE *fp;
6434{
6435 char *eof;
6436#define FGETS_SIZE 200
6437 char tbuf[FGETS_SIZE];
6438
6439 buf[size - 2] = NUL;
6440#ifdef USE_CR
6441 eof = fgets_cr((char *)buf, size, fp);
6442#else
6443 eof = fgets((char *)buf, size, fp);
6444#endif
6445 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
6446 {
6447 buf[size - 1] = NUL; /* Truncate the line */
6448
6449 /* Now throw away the rest of the line: */
6450 do
6451 {
6452 tbuf[FGETS_SIZE - 2] = NUL;
6453#ifdef USE_CR
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006454 ignoredp = fgets_cr((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006455#else
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006456 ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006457#endif
6458 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
6459 }
6460 return (eof == NULL);
6461}
6462
6463#if defined(USE_CR) || defined(PROTO)
6464/*
6465 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
6466 * Returns TRUE for end-of-file.
6467 * Only used for the Mac, because it's much slower than vim_fgets().
6468 */
6469 int
6470tag_fgets(buf, size, fp)
6471 char_u *buf;
6472 int size;
6473 FILE *fp;
6474{
6475 int i = 0;
6476 int c;
6477 int eof = FALSE;
6478
6479 for (;;)
6480 {
6481 c = fgetc(fp);
6482 if (c == EOF)
6483 {
6484 eof = TRUE;
6485 break;
6486 }
6487 if (c == '\r')
6488 {
6489 /* Always store a NL for end-of-line. */
6490 if (i < size - 1)
6491 buf[i++] = '\n';
6492 c = fgetc(fp);
6493 if (c != '\n') /* Macintosh format: single CR. */
6494 ungetc(c, fp);
6495 break;
6496 }
6497 if (i < size - 1)
6498 buf[i++] = c;
6499 if (c == '\n')
6500 break;
6501 }
6502 buf[i] = NUL;
6503 return eof;
6504}
6505#endif
6506
6507/*
6508 * rename() only works if both files are on the same file system, this
6509 * function will (attempts to?) copy the file across if rename fails -- webb
6510 * Return -1 for failure, 0 for success.
6511 */
6512 int
6513vim_rename(from, to)
6514 char_u *from;
6515 char_u *to;
6516{
6517 int fd_in;
6518 int fd_out;
6519 int n;
6520 char *errmsg = NULL;
6521 char *buffer;
6522#ifdef AMIGA
6523 BPTR flock;
6524#endif
6525 struct stat st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006526 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006527#ifdef HAVE_ACL
6528 vim_acl_T acl; /* ACL from original file */
6529#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006530 int use_tmp_file = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006531
6532 /*
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006533 * When the names are identical, there is nothing to do. When they refer
6534 * to the same file (ignoring case and slash/backslash differences) but
6535 * the file name differs we need to go through a temp file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006536 */
6537 if (fnamecmp(from, to) == 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006538 {
Bram Moolenaar71afbfe2013-03-19 16:49:16 +01006539 if (p_fic && STRCMP(gettail(from), gettail(to)) != 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006540 use_tmp_file = TRUE;
6541 else
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006542 return 0;
6543 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006544
6545 /*
6546 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
6547 */
6548 if (mch_stat((char *)from, &st) < 0)
6549 return -1;
6550
Bram Moolenaar3576da72008-12-30 15:15:57 +00006551#ifdef UNIX
6552 {
6553 struct stat st_to;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006554
6555 /* It's possible for the source and destination to be the same file.
6556 * This happens when "from" and "to" differ in case and are on a FAT32
6557 * filesystem. In that case go through a temp file name. */
6558 if (mch_stat((char *)to, &st_to) >= 0
6559 && st.st_dev == st_to.st_dev
6560 && st.st_ino == st_to.st_ino)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006561 use_tmp_file = TRUE;
6562 }
6563#endif
Bram Moolenaar1c32dff2011-05-05 16:41:24 +02006564#ifdef WIN3264
6565 {
6566 BY_HANDLE_FILE_INFORMATION info1, info2;
6567
6568 /* It's possible for the source and destination to be the same file.
6569 * In that case go through a temp file name. This makes rename("foo",
6570 * "./foo") a no-op (in a complicated way). */
6571 if (win32_fileinfo(from, &info1) == FILEINFO_OK
6572 && win32_fileinfo(to, &info2) == FILEINFO_OK
6573 && info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
6574 && info1.nFileIndexHigh == info2.nFileIndexHigh
6575 && info1.nFileIndexLow == info2.nFileIndexLow)
6576 use_tmp_file = TRUE;
6577 }
6578#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006579
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006580 if (use_tmp_file)
6581 {
6582 char tempname[MAXPATHL + 1];
6583
6584 /*
6585 * Find a name that doesn't exist and is in the same directory.
6586 * Rename "from" to "tempname" and then rename "tempname" to "to".
6587 */
6588 if (STRLEN(from) >= MAXPATHL - 5)
6589 return -1;
6590 STRCPY(tempname, from);
6591 for (n = 123; n < 99999; ++n)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006592 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006593 sprintf((char *)gettail((char_u *)tempname), "%d", n);
6594 if (mch_stat(tempname, &st) < 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006595 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006596 if (mch_rename((char *)from, tempname) == 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006597 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006598 if (mch_rename(tempname, (char *)to) == 0)
6599 return 0;
6600 /* Strange, the second step failed. Try moving the
6601 * file back and return failure. */
6602 mch_rename(tempname, (char *)from);
Bram Moolenaar3576da72008-12-30 15:15:57 +00006603 return -1;
6604 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006605 /* If it fails for one temp name it will most likely fail
6606 * for any temp name, give up. */
6607 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006608 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006609 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006610 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006611 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006612
Bram Moolenaar071d4272004-06-13 20:20:40 +00006613 /*
6614 * Delete the "to" file, this is required on some systems to make the
6615 * mch_rename() work, on other systems it makes sure that we don't have
6616 * two files when the mch_rename() fails.
6617 */
6618
6619#ifdef AMIGA
6620 /*
6621 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
6622 * that the name of the "to" file is the same as the "from" file, even
Bram Moolenaar7263a772007-05-10 17:35:54 +00006623 * though the names are different. To avoid the chance of accidentally
Bram Moolenaar071d4272004-06-13 20:20:40 +00006624 * deleting the "from" file (horror!) we lock it during the remove.
6625 *
6626 * When used for making a backup before writing the file: This should not
6627 * happen with ":w", because startscript() should detect this problem and
6628 * set buf->b_shortname, causing modname() to return a correct ".bak" file
6629 * name. This problem does exist with ":w filename", but then the
6630 * original file will be somewhere else so the backup isn't really
6631 * important. If autoscripting is off the rename may fail.
6632 */
6633 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
6634#endif
6635 mch_remove(to);
6636#ifdef AMIGA
6637 if (flock)
6638 UnLock(flock);
6639#endif
6640
6641 /*
6642 * First try a normal rename, return if it works.
6643 */
6644 if (mch_rename((char *)from, (char *)to) == 0)
6645 return 0;
6646
6647 /*
6648 * Rename() failed, try copying the file.
6649 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006650 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006651#ifdef HAVE_ACL
6652 /* For systems that support ACL: get the ACL from the original file. */
6653 acl = mch_get_acl(from);
6654#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006655 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
6656 if (fd_in == -1)
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006657 {
6658#ifdef HAVE_ACL
6659 mch_free_acl(acl);
6660#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006661 return -1;
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006662 }
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006663
6664 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00006665 fd_out = mch_open((char *)to,
6666 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006667 if (fd_out == -1)
6668 {
6669 close(fd_in);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006670#ifdef HAVE_ACL
6671 mch_free_acl(acl);
6672#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006673 return -1;
6674 }
6675
6676 buffer = (char *)alloc(BUFSIZE);
6677 if (buffer == NULL)
6678 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006679 close(fd_out);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006680 close(fd_in);
6681#ifdef HAVE_ACL
6682 mch_free_acl(acl);
6683#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006684 return -1;
6685 }
6686
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01006687 while ((n = read_eintr(fd_in, buffer, BUFSIZE)) > 0)
6688 if (write_eintr(fd_out, buffer, n) != n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006689 {
6690 errmsg = _("E208: Error writing to \"%s\"");
6691 break;
6692 }
6693
6694 vim_free(buffer);
6695 close(fd_in);
6696 if (close(fd_out) < 0)
6697 errmsg = _("E209: Error closing \"%s\"");
6698 if (n < 0)
6699 {
6700 errmsg = _("E210: Error reading \"%s\"");
6701 to = from;
6702 }
Bram Moolenaar7263a772007-05-10 17:35:54 +00006703#ifndef UNIX /* for Unix mch_open() already set the permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006704 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00006705#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006706#ifdef HAVE_ACL
6707 mch_set_acl(to, acl);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006708 mch_free_acl(acl);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006709#endif
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02006710#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
Bram Moolenaare8747442013-11-12 18:09:29 +01006711 mch_copy_sec(from, to);
Bram Moolenaar0671de32013-11-12 05:12:03 +01006712#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006713 if (errmsg != NULL)
6714 {
6715 EMSG2(errmsg, to);
6716 return -1;
6717 }
6718 mch_remove(from);
6719 return 0;
6720}
6721
6722static int already_warned = FALSE;
6723
6724/*
6725 * Check if any not hidden buffer has been changed.
6726 * Postpone the check if there are characters in the stuff buffer, a global
6727 * command is being executed, a mapping is being executed or an autocommand is
6728 * busy.
6729 * Returns TRUE if some message was written (screen should be redrawn and
6730 * cursor positioned).
6731 */
6732 int
6733check_timestamps(focus)
6734 int focus; /* called for GUI focus event */
6735{
6736 buf_T *buf;
6737 int didit = 0;
6738 int n;
6739
6740 /* Don't check timestamps while system() or another low-level function may
6741 * cause us to lose and gain focus. */
6742 if (no_check_timestamps > 0)
6743 return FALSE;
6744
6745 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6746 * event and we would keep on checking if the file is steadily growing.
6747 * Do check again after typing something. */
6748 if (focus && did_check_timestamps)
6749 {
6750 need_check_timestamps = TRUE;
6751 return FALSE;
6752 }
6753
6754 if (!stuff_empty() || global_busy || !typebuf_typed()
6755#ifdef FEAT_AUTOCMD
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006756 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006757#endif
6758 )
6759 need_check_timestamps = TRUE; /* check later */
6760 else
6761 {
6762 ++no_wait_return;
6763 did_check_timestamps = TRUE;
6764 already_warned = FALSE;
6765 for (buf = firstbuf; buf != NULL; )
6766 {
6767 /* Only check buffers in a window. */
6768 if (buf->b_nwindows > 0)
6769 {
6770 n = buf_check_timestamp(buf, focus);
6771 if (didit < n)
6772 didit = n;
6773 if (n > 0 && !buf_valid(buf))
6774 {
6775 /* Autocommands have removed the buffer, start at the
6776 * first one again. */
6777 buf = firstbuf;
6778 continue;
6779 }
6780 }
6781 buf = buf->b_next;
6782 }
6783 --no_wait_return;
6784 need_check_timestamps = FALSE;
6785 if (need_wait_return && didit == 2)
6786 {
6787 /* make sure msg isn't overwritten */
6788 msg_puts((char_u *)"\n");
6789 out_flush();
6790 }
6791 }
6792 return didit;
6793}
6794
6795/*
6796 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6797 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6798 * empty.
6799 */
6800 static int
6801move_lines(frombuf, tobuf)
6802 buf_T *frombuf;
6803 buf_T *tobuf;
6804{
6805 buf_T *tbuf = curbuf;
6806 int retval = OK;
6807 linenr_T lnum;
6808 char_u *p;
6809
6810 /* Copy the lines in "frombuf" to "tobuf". */
6811 curbuf = tobuf;
6812 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6813 {
6814 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6815 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6816 {
6817 vim_free(p);
6818 retval = FAIL;
6819 break;
6820 }
6821 vim_free(p);
6822 }
6823
6824 /* Delete all the lines in "frombuf". */
6825 if (retval != FAIL)
6826 {
6827 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006828 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6829 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006830 {
6831 /* Oops! We could try putting back the saved lines, but that
6832 * might fail again... */
6833 retval = FAIL;
6834 break;
6835 }
6836 }
6837
6838 curbuf = tbuf;
6839 return retval;
6840}
6841
6842/*
6843 * Check if buffer "buf" has been changed.
6844 * Also check if the file for a new buffer unexpectedly appeared.
6845 * return 1 if a changed buffer was found.
6846 * return 2 if a message has been displayed.
6847 * return 0 otherwise.
6848 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006849 int
6850buf_check_timestamp(buf, focus)
6851 buf_T *buf;
Bram Moolenaar78a15312009-05-15 19:33:18 +00006852 int focus UNUSED; /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006853{
6854 struct stat st;
6855 int stat_res;
6856 int retval = 0;
6857 char_u *path;
6858 char_u *tbuf;
6859 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006860 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006861 int helpmesg = FALSE;
6862 int reload = FALSE;
6863#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6864 int can_reload = FALSE;
6865#endif
Bram Moolenaar914703b2010-05-31 21:59:46 +02006866 off_t orig_size = buf->b_orig_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006867 int orig_mode = buf->b_orig_mode;
6868#ifdef FEAT_GUI
6869 int save_mouse_correct = need_mouse_correct;
6870#endif
6871#ifdef FEAT_AUTOCMD
6872 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006873 int n;
6874 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006875#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006876 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006877
6878 /* If there is no file name, the buffer is not loaded, 'buftype' is
6879 * set, we are in the middle of a save or being called recursively: ignore
6880 * this buffer. */
6881 if (buf->b_ffname == NULL
6882 || buf->b_ml.ml_mfp == NULL
6883#if defined(FEAT_QUICKFIX)
6884 || *buf->b_p_bt != NUL
6885#endif
6886 || buf->b_saving
6887#ifdef FEAT_AUTOCMD
6888 || busy
6889#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006890#ifdef FEAT_NETBEANS_INTG
6891 || isNetbeansBuffer(buf)
6892#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006893 )
6894 return 0;
6895
6896 if ( !(buf->b_flags & BF_NOTEDITED)
6897 && buf->b_mtime != 0
6898 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6899 || time_differs((long)st.st_mtime, buf->b_mtime)
6900#ifdef HAVE_ST_MODE
6901 || (int)st.st_mode != buf->b_orig_mode
6902#else
6903 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6904#endif
6905 ))
6906 {
6907 retval = 1;
6908
Bram Moolenaar316059c2006-01-14 21:18:42 +00006909 /* set b_mtime to stop further warnings (e.g., when executing
6910 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006911 if (stat_res < 0)
6912 {
6913 buf->b_mtime = 0;
6914 buf->b_orig_size = 0;
6915 buf->b_orig_mode = 0;
6916 }
6917 else
6918 buf_store_time(buf, &st, buf->b_ffname);
6919
6920 /* Don't do anything for a directory. Might contain the file
6921 * explorer. */
6922 if (mch_isdir(buf->b_fname))
6923 ;
6924
6925 /*
6926 * If 'autoread' is set, the buffer has no changes and the file still
6927 * exists, reload the buffer. Use the buffer-local option value if it
6928 * was set, the global option value otherwise.
6929 */
6930 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6931 && !bufIsChanged(buf) && stat_res >= 0)
6932 reload = TRUE;
6933 else
6934 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006935 if (stat_res < 0)
6936 reason = "deleted";
6937 else if (bufIsChanged(buf))
6938 reason = "conflict";
6939 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6940 reason = "changed";
6941 else if (orig_mode != buf->b_orig_mode)
6942 reason = "mode";
6943 else
6944 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006945
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006946#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006947 /*
6948 * Only give the warning if there are no FileChangedShell
6949 * autocommands.
6950 * Avoid being called recursively by setting "busy".
6951 */
6952 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006953# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006954 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6955 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006956# endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006957 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006958 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6959 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006960 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006961 busy = FALSE;
6962 if (n)
6963 {
6964 if (!buf_valid(buf))
6965 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006966# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006967 s = get_vim_var_str(VV_FCS_CHOICE);
6968 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6969 reload = TRUE;
6970 else if (STRCMP(s, "ask") == 0)
6971 n = FALSE;
6972 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006973# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006974 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006975 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006976 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006977#endif
6978 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006979 if (*reason == 'd')
6980 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006981 else
6982 {
6983 helpmesg = TRUE;
6984#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6985 can_reload = TRUE;
6986#endif
6987 /*
6988 * Check if the file contents really changed to avoid
6989 * giving a warning when only the timestamp was set (e.g.,
6990 * checked out of CVS). Always warn when the buffer was
6991 * changed.
6992 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006993 if (reason[2] == 'n')
6994 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006995 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006996 mesg2 = _("See \":help W12\" for more info.");
6997 }
6998 else if (reason[1] == 'h')
6999 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007000 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007001 mesg2 = _("See \":help W11\" for more info.");
7002 }
7003 else if (*reason == 'm')
7004 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007005 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007006 mesg2 = _("See \":help W16\" for more info.");
7007 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00007008 else
7009 /* Only timestamp changed, store it to avoid a warning
7010 * in check_mtime() later. */
7011 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007012 }
7013 }
7014 }
7015
7016 }
7017 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
7018 && vim_fexists(buf->b_ffname))
7019 {
7020 retval = 1;
7021 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
7022 buf->b_flags |= BF_NEW_W;
7023#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7024 can_reload = TRUE;
7025#endif
7026 }
7027
7028 if (mesg != NULL)
7029 {
7030 path = home_replace_save(buf, buf->b_fname);
7031 if (path != NULL)
7032 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007033 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007034 mesg2 = "";
7035 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
7036 + STRLEN(mesg2) + 2));
7037 sprintf((char *)tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00007038#ifdef FEAT_EVAL
7039 /* Set warningmsg here, before the unimportant and output-specific
7040 * mesg2 has been appended. */
7041 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
7042#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007043#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7044 if (can_reload)
7045 {
7046 if (*mesg2 != NUL)
7047 {
7048 STRCAT(tbuf, "\n");
7049 STRCAT(tbuf, mesg2);
7050 }
7051 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01007052 (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007053 reload = TRUE;
7054 }
7055 else
7056#endif
7057 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
7058 {
7059 if (*mesg2 != NUL)
7060 {
7061 STRCAT(tbuf, "; ");
7062 STRCAT(tbuf, mesg2);
7063 }
7064 EMSG(tbuf);
7065 retval = 2;
7066 }
7067 else
7068 {
Bram Moolenaared203462004-06-16 11:19:22 +00007069# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00007070 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00007071# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007072 {
7073 msg_start();
7074 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
7075 if (*mesg2 != NUL)
7076 msg_puts_attr((char_u *)mesg2,
7077 hl_attr(HLF_W) + MSG_HIST);
7078 msg_clr_eos();
7079 (void)msg_end();
7080 if (emsg_silent == 0)
7081 {
7082 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00007083# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00007084 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00007085# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007086 /* give the user some time to think about it */
7087 ui_delay(1000L, TRUE);
7088
7089 /* don't redraw and erase the message */
7090 redraw_cmdline = FALSE;
7091 }
7092 }
7093 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007094 }
7095
7096 vim_free(path);
7097 vim_free(tbuf);
7098 }
7099 }
7100
7101 if (reload)
Bram Moolenaar465748e2012-08-29 18:50:54 +02007102 {
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007103 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00007104 buf_reload(buf, orig_mode);
Bram Moolenaar465748e2012-08-29 18:50:54 +02007105#ifdef FEAT_PERSISTENT_UNDO
7106 if (buf->b_p_udf && buf->b_ffname != NULL)
7107 {
7108 char_u hash[UNDO_HASH_SIZE];
7109 buf_T *save_curbuf = curbuf;
7110
7111 /* Any existing undo file is unusable, write it now. */
7112 curbuf = buf;
7113 u_compute_hash(hash);
7114 u_write_undo(NULL, FALSE, buf, hash);
7115 curbuf = save_curbuf;
7116 }
7117#endif
7118 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007119
Bram Moolenaar56718732006-03-15 22:53:57 +00007120#ifdef FEAT_AUTOCMD
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00007121 /* Trigger FileChangedShell when the file was changed in any way. */
7122 if (buf_valid(buf) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00007123 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
7124 buf->b_fname, buf->b_fname, FALSE, buf);
7125#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007126#ifdef FEAT_GUI
7127 /* restore this in case an autocommand has set it; it would break
7128 * 'mousefocus' */
7129 need_mouse_correct = save_mouse_correct;
7130#endif
7131
7132 return retval;
7133}
7134
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007135/*
7136 * Reload a buffer that is already loaded.
7137 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00007138 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
7139 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007140 */
7141 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00007142buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007143 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00007144 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007145{
7146 exarg_T ea;
7147 pos_T old_cursor;
7148 linenr_T old_topline;
7149 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007150 buf_T *savebuf;
7151 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007152 aco_save_T aco;
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007153 int flags = READ_NEW;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007154
7155 /* set curwin/curbuf for "buf" and save some things */
7156 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007157
7158 /* We only want to read the text from the file, not reset the syntax
7159 * highlighting, clear marks, diff status, etc. Force the fileformat
7160 * and encoding to be the same. */
7161 if (prep_exarg(&ea, buf) == OK)
7162 {
7163 old_cursor = curwin->w_cursor;
7164 old_topline = curwin->w_topline;
7165
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007166 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007167 {
7168 /* Save all the text, so that the reload can be undone.
7169 * Sync first so that this is a separate undo-able action. */
7170 u_sync(FALSE);
7171 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
7172 flags |= READ_KEEP_UNDO;
7173 }
7174
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007175 /*
7176 * To behave like when a new file is edited (matters for
7177 * BufReadPost autocommands) we first need to delete the current
7178 * buffer contents. But if reading the file fails we should keep
7179 * the old contents. Can't use memory only, the file might be
7180 * too big. Use a hidden buffer to move the buffer contents to.
7181 */
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007182 if (bufempty() || saved == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007183 savebuf = NULL;
7184 else
7185 {
7186 /* Allocate a buffer without putting it in the buffer list. */
7187 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007188 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007189 {
7190 /* Open the memline. */
7191 curbuf = savebuf;
7192 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00007193 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007194 curbuf = buf;
7195 curwin->w_buffer = buf;
7196 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00007197 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007198 || move_lines(buf, savebuf) == FAIL)
7199 {
7200 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
7201 buf->b_fname);
7202 saved = FAIL;
7203 }
7204 }
7205
7206 if (saved == OK)
7207 {
7208 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
7209#ifdef FEAT_AUTOCMD
7210 keep_filetype = TRUE; /* don't detect 'filetype' */
7211#endif
7212 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
7213 (linenr_T)0,
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007214 (linenr_T)MAXLNUM, &ea, flags) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007215 {
7216#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
7217 if (!aborting())
7218#endif
7219 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007220 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007221 {
7222 /* Put the text back from the save buffer. First
7223 * delete any lines that readfile() added. */
7224 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00007225 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007226 break;
7227 (void)move_lines(savebuf, buf);
7228 }
7229 }
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007230 else if (buf == curbuf) /* "buf" still valid */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007231 {
7232 /* Mark the buffer as unmodified and free undo info. */
7233 unchanged(buf, TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007234 if ((flags & READ_KEEP_UNDO) == 0)
7235 {
7236 u_blockfree(buf);
7237 u_clearall(buf);
7238 }
7239 else
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007240 {
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007241 /* Mark all undo states as changed. */
7242 u_unchanged(curbuf);
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007243 }
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007244 }
7245 }
7246 vim_free(ea.cmd);
7247
Bram Moolenaar8424a622006-04-19 21:23:36 +00007248 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007249 wipe_buffer(savebuf, FALSE);
7250
7251#ifdef FEAT_DIFF
7252 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00007253 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007254#endif
7255
7256 /* Restore the topline and cursor position and check it (lines may
7257 * have been removed). */
7258 if (old_topline > curbuf->b_ml.ml_line_count)
7259 curwin->w_topline = curbuf->b_ml.ml_line_count;
7260 else
7261 curwin->w_topline = old_topline;
7262 curwin->w_cursor = old_cursor;
7263 check_cursor();
7264 update_topline();
7265#ifdef FEAT_AUTOCMD
7266 keep_filetype = FALSE;
7267#endif
7268#ifdef FEAT_FOLDING
7269 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007270 win_T *wp;
7271 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007272
7273 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007274 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007275 if (wp->w_buffer == curwin->w_buffer
7276 && !foldmethodIsManual(wp))
7277 foldUpdateAll(wp);
7278 }
7279#endif
7280 /* If the mode didn't change and 'readonly' was set, keep the old
7281 * value; the user probably used the ":view" command. But don't
7282 * reset it, might have had a read error. */
7283 if (orig_mode == curbuf->b_orig_mode)
7284 curbuf->b_p_ro |= old_ro;
Bram Moolenaar52f85b72013-01-30 14:13:56 +01007285
7286 /* Modelines must override settings done by autocommands. */
7287 do_modelines(0);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007288 }
7289
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007290 /* restore curwin/curbuf and a few other things */
7291 aucmd_restbuf(&aco);
7292 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007293}
7294
Bram Moolenaar071d4272004-06-13 20:20:40 +00007295 void
7296buf_store_time(buf, st, fname)
7297 buf_T *buf;
7298 struct stat *st;
Bram Moolenaar78a15312009-05-15 19:33:18 +00007299 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007300{
7301 buf->b_mtime = (long)st->st_mtime;
Bram Moolenaar914703b2010-05-31 21:59:46 +02007302 buf->b_orig_size = st->st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007303#ifdef HAVE_ST_MODE
7304 buf->b_orig_mode = (int)st->st_mode;
7305#else
7306 buf->b_orig_mode = mch_getperm(fname);
7307#endif
7308}
7309
7310/*
7311 * Adjust the line with missing eol, used for the next write.
7312 * Used for do_filter(), when the input lines for the filter are deleted.
7313 */
7314 void
7315write_lnum_adjust(offset)
7316 linenr_T offset;
7317{
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01007318 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
7319 curbuf->b_no_eol_lnum += offset;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007320}
7321
7322#if defined(TEMPDIRNAMES) || defined(PROTO)
7323static long temp_count = 0; /* Temp filename counter. */
7324
7325/*
7326 * Delete the temp directory and all files it contains.
7327 */
7328 void
7329vim_deltempdir()
7330{
7331 char_u **files;
7332 int file_count;
7333 int i;
7334
7335 if (vim_tempdir != NULL)
7336 {
7337 sprintf((char *)NameBuff, "%s*", vim_tempdir);
7338 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
7339 EW_DIR|EW_FILE|EW_SILENT) == OK)
7340 {
7341 for (i = 0; i < file_count; ++i)
7342 mch_remove(files[i]);
7343 FreeWild(file_count, files);
7344 }
7345 gettail(NameBuff)[-1] = NUL;
7346 (void)mch_rmdir(NameBuff);
7347
7348 vim_free(vim_tempdir);
7349 vim_tempdir = NULL;
7350 }
7351}
7352#endif
7353
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007354#ifdef TEMPDIRNAMES
Bram Moolenaar071d4272004-06-13 20:20:40 +00007355/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007356 * Directory "tempdir" was created. Expand this name to a full path and put
7357 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7358 * "tempdir" must be no longer than MAXPATHL.
7359 */
7360 static void
7361vim_settempdir(tempdir)
7362 char_u *tempdir;
7363{
7364 char_u *buf;
7365
7366 buf = alloc((unsigned)MAXPATHL + 2);
7367 if (buf != NULL)
7368 {
7369 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7370 STRCPY(buf, tempdir);
7371# ifdef __EMX__
7372 if (vim_strchr(buf, '/') != NULL)
7373 STRCAT(buf, "/");
7374 else
7375# endif
7376 add_pathsep(buf);
7377 vim_tempdir = vim_strsave(buf);
7378 vim_free(buf);
7379 }
7380}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007381#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007382
7383/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007384 * vim_tempname(): Return a unique name that can be used for a temp file.
7385 *
7386 * The temp file is NOT created.
7387 *
7388 * The returned pointer is to allocated memory.
7389 * The returned pointer is NULL if no valid name was found.
7390 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007391 char_u *
7392vim_tempname(extra_char)
Bram Moolenaar78a15312009-05-15 19:33:18 +00007393 int extra_char UNUSED; /* char to use in the name instead of '?' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007394{
7395#ifdef USE_TMPNAM
7396 char_u itmp[L_tmpnam]; /* use tmpnam() */
7397#else
7398 char_u itmp[TEMPNAMELEN];
7399#endif
7400
7401#ifdef TEMPDIRNAMES
7402 static char *(tempdirs[]) = {TEMPDIRNAMES};
7403 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007404# ifndef EEXIST
7405 struct stat st;
7406# endif
7407
7408 /*
7409 * This will create a directory for private use by this instance of Vim.
7410 * This is done once, and the same directory is used for all temp files.
7411 * This method avoids security problems because of symlink attacks et al.
7412 * It's also a bit faster, because we only need to check for an existing
7413 * file when creating the directory and not for each temp file.
7414 */
7415 if (vim_tempdir == NULL)
7416 {
7417 /*
7418 * Try the entries in TEMPDIRNAMES to create the temp directory.
7419 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007420 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007421 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007422# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007423 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007424 long nr;
7425 long off;
7426# endif
7427
Bram Moolenaar071d4272004-06-13 20:20:40 +00007428 /* expand $TMP, leave room for "/v1100000/999999999" */
7429 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
7430 if (mch_isdir(itmp)) /* directory exists */
7431 {
7432# ifdef __EMX__
7433 /* If $TMP contains a forward slash (perhaps using bash or
7434 * tcsh), don't add a backslash, use a forward slash!
7435 * Adding 2 backslashes didn't work. */
7436 if (vim_strchr(itmp, '/') != NULL)
7437 STRCAT(itmp, "/");
7438 else
7439# endif
7440 add_pathsep(itmp);
7441
Bram Moolenaareaf03392009-11-17 11:08:52 +00007442# ifdef HAVE_MKDTEMP
7443 /* Leave room for filename */
7444 STRCAT(itmp, "vXXXXXX");
7445 if (mkdtemp((char *)itmp) != NULL)
7446 vim_settempdir(itmp);
7447# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007448 /* Get an arbitrary number of up to 6 digits. When it's
7449 * unlikely that it already exists it will be faster,
7450 * otherwise it doesn't matter. The use of mkdir() avoids any
7451 * security problems because of the predictable number. */
7452 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007453 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007454
7455 /* Try up to 10000 different values until we find a name that
7456 * doesn't exist. */
7457 for (off = 0; off < 10000L; ++off)
7458 {
7459 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007460# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007461 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007462# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007463
Bram Moolenaareaf03392009-11-17 11:08:52 +00007464 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7465# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466 /* If mkdir() does not set errno to EEXIST, check for
7467 * existing file here. There is a race condition then,
7468 * although it's fail-safe. */
7469 if (mch_stat((char *)itmp, &st) >= 0)
7470 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007471# endif
7472# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007473 /* Make sure the umask doesn't remove the executable bit.
7474 * "repl" has been reported to use "177". */
7475 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007476# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007477 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007478# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007479 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007480# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007481 if (r == 0)
7482 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007483 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007484 break;
7485 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007486# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007487 /* If the mkdir() didn't fail because the file/dir exists,
7488 * we probably can't create any dir here, try another
7489 * place. */
7490 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007491# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007492 break;
7493 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007494# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007495 if (vim_tempdir != NULL)
7496 break;
7497 }
7498 }
7499 }
7500
7501 if (vim_tempdir != NULL)
7502 {
7503 /* There is no need to check if the file exists, because we own the
7504 * directory and nobody else creates a file in it. */
7505 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7506 return vim_strsave(itmp);
7507 }
7508
7509 return NULL;
7510
7511#else /* TEMPDIRNAMES */
7512
7513# ifdef WIN3264
7514 char szTempFile[_MAX_PATH + 1];
7515 char buf4[4];
7516 char_u *retval;
7517 char_u *p;
7518
7519 STRCPY(itmp, "");
7520 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
Bram Moolenaarb1891912011-02-09 14:47:03 +01007521 {
7522 szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */
7523 szTempFile[1] = NUL;
7524 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007525 strcpy(buf4, "VIM");
7526 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
7527 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
7528 return NULL;
7529 /* GetTempFileName() will create the file, we don't want that */
7530 (void)DeleteFile(itmp);
7531
7532 /* Backslashes in a temp file name cause problems when filtering with
7533 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7534 * didn't set 'shellslash'. */
7535 retval = vim_strsave(itmp);
7536 if (*p_shcf == '-' || p_ssl)
7537 for (p = retval; *p; ++p)
7538 if (*p == '\\')
7539 *p = '/';
7540 return retval;
7541
7542# else /* WIN3264 */
7543
7544# ifdef USE_TMPNAM
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007545 char_u *p;
7546
Bram Moolenaar071d4272004-06-13 20:20:40 +00007547 /* tmpnam() will make its own name */
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007548 p = tmpnam((char *)itmp);
7549 if (p == NULL || *p == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007550 return NULL;
7551# else
7552 char_u *p;
7553
7554# ifdef VMS_TEMPNAM
7555 /* mktemp() is not working on VMS. It seems to be
7556 * a do-nothing function. Therefore we use tempnam().
7557 */
7558 sprintf((char *)itmp, "VIM%c", extra_char);
7559 p = (char_u *)tempnam("tmp:", (char *)itmp);
7560 if (p != NULL)
7561 {
Bram Moolenaar206f0112014-03-12 16:51:55 +01007562 /* VMS will use '.LIS' if we don't explicitly specify an extension,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007563 * and VIM will then be unable to find the file later */
7564 STRCPY(itmp, p);
7565 STRCAT(itmp, ".txt");
7566 free(p);
7567 }
7568 else
7569 return NULL;
7570# else
7571 STRCPY(itmp, TEMPNAME);
7572 if ((p = vim_strchr(itmp, '?')) != NULL)
7573 *p = extra_char;
7574 if (mktemp((char *)itmp) == NULL)
7575 return NULL;
7576# endif
7577# endif
7578
7579 return vim_strsave(itmp);
7580# endif /* WIN3264 */
7581#endif /* TEMPDIRNAMES */
7582}
7583
7584#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7585/*
7586 * Convert all backslashes in fname to forward slashes in-place.
7587 */
7588 void
7589forward_slash(fname)
7590 char_u *fname;
7591{
7592 char_u *p;
7593
7594 for (p = fname; *p != NUL; ++p)
7595# ifdef FEAT_MBYTE
7596 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007597 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007598 ++p;
7599 else
7600# endif
7601 if (*p == '\\')
7602 *p = '/';
7603}
7604#endif
7605
7606
7607/*
7608 * Code for automatic commands.
7609 *
7610 * Only included when "FEAT_AUTOCMD" has been defined.
7611 */
7612
7613#if defined(FEAT_AUTOCMD) || defined(PROTO)
7614
7615/*
7616 * The autocommands are stored in a list for each event.
7617 * Autocommands for the same pattern, that are consecutive, are joined
7618 * together, to avoid having to match the pattern too often.
7619 * The result is an array of Autopat lists, which point to AutoCmd lists:
7620 *
7621 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7622 * Autopat.cmds Autopat.cmds
7623 * | |
7624 * V V
7625 * AutoCmd.next AutoCmd.next
7626 * | |
7627 * V V
7628 * AutoCmd.next NULL
7629 * |
7630 * V
7631 * NULL
7632 *
7633 * first_autopat[1] --> Autopat.next --> NULL
7634 * Autopat.cmds
7635 * |
7636 * V
7637 * AutoCmd.next
7638 * |
7639 * V
7640 * NULL
7641 * etc.
7642 *
7643 * The order of AutoCmds is important, this is the order in which they were
7644 * defined and will have to be executed.
7645 */
7646typedef struct AutoCmd
7647{
7648 char_u *cmd; /* The command to be executed (NULL
7649 when command has been removed) */
7650 char nested; /* If autocommands nest here */
7651 char last; /* last command in list */
7652#ifdef FEAT_EVAL
7653 scid_T scriptID; /* script ID where defined */
7654#endif
7655 struct AutoCmd *next; /* Next AutoCmd in list */
7656} AutoCmd;
7657
7658typedef struct AutoPat
7659{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007660 char_u *pat; /* pattern as typed (NULL when pattern
7661 has been removed) */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007662 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007663 AutoCmd *cmds; /* list of commands to do */
7664 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007665 int group; /* group ID */
7666 int patlen; /* strlen() of pat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007667 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007668 char allow_dirs; /* Pattern may match whole path */
7669 char last; /* last pattern for apply_autocmds() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007670} AutoPat;
7671
7672static struct event_name
7673{
7674 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007675 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007676} event_names[] =
7677{
7678 {"BufAdd", EVENT_BUFADD},
7679 {"BufCreate", EVENT_BUFADD},
7680 {"BufDelete", EVENT_BUFDELETE},
7681 {"BufEnter", EVENT_BUFENTER},
7682 {"BufFilePost", EVENT_BUFFILEPOST},
7683 {"BufFilePre", EVENT_BUFFILEPRE},
7684 {"BufHidden", EVENT_BUFHIDDEN},
7685 {"BufLeave", EVENT_BUFLEAVE},
7686 {"BufNew", EVENT_BUFNEW},
7687 {"BufNewFile", EVENT_BUFNEWFILE},
7688 {"BufRead", EVENT_BUFREADPOST},
7689 {"BufReadCmd", EVENT_BUFREADCMD},
7690 {"BufReadPost", EVENT_BUFREADPOST},
7691 {"BufReadPre", EVENT_BUFREADPRE},
7692 {"BufUnload", EVENT_BUFUNLOAD},
7693 {"BufWinEnter", EVENT_BUFWINENTER},
7694 {"BufWinLeave", EVENT_BUFWINLEAVE},
7695 {"BufWipeout", EVENT_BUFWIPEOUT},
7696 {"BufWrite", EVENT_BUFWRITEPRE},
7697 {"BufWritePost", EVENT_BUFWRITEPOST},
7698 {"BufWritePre", EVENT_BUFWRITEPRE},
7699 {"BufWriteCmd", EVENT_BUFWRITECMD},
7700 {"CmdwinEnter", EVENT_CMDWINENTER},
7701 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007702 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaarcfa3cae2012-07-10 17:14:56 +02007703 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007704 {"CursorHold", EVENT_CURSORHOLD},
7705 {"CursorHoldI", EVENT_CURSORHOLDI},
7706 {"CursorMoved", EVENT_CURSORMOVED},
7707 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007708 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7709 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007710 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7711 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7712 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7713 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007714 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007715 {"FileChangedRO", EVENT_FILECHANGEDRO},
7716 {"FileReadPost", EVENT_FILEREADPOST},
7717 {"FileReadPre", EVENT_FILEREADPRE},
7718 {"FileReadCmd", EVENT_FILEREADCMD},
7719 {"FileType", EVENT_FILETYPE},
7720 {"FileWritePost", EVENT_FILEWRITEPOST},
7721 {"FileWritePre", EVENT_FILEWRITEPRE},
7722 {"FileWriteCmd", EVENT_FILEWRITECMD},
7723 {"FilterReadPost", EVENT_FILTERREADPOST},
7724 {"FilterReadPre", EVENT_FILTERREADPRE},
7725 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7726 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7727 {"FocusGained", EVENT_FOCUSGAINED},
7728 {"FocusLost", EVENT_FOCUSLOST},
7729 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7730 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007731 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007732 {"InsertChange", EVENT_INSERTCHANGE},
7733 {"InsertEnter", EVENT_INSERTENTER},
7734 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaare659c952011-05-19 17:25:41 +02007735 {"InsertCharPre", EVENT_INSERTCHARPRE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007736 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007737 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7738 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar3b53dfb2012-06-06 18:03:07 +02007739 {"QuitPre", EVENT_QUITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007740 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007741 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007742 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7743 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007744 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007745 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007746 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007747 {"StdinReadPost", EVENT_STDINREADPOST},
7748 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007749 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007750 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007751 {"TabEnter", EVENT_TABENTER},
7752 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007753 {"TermChanged", EVENT_TERMCHANGED},
7754 {"TermResponse", EVENT_TERMRESPONSE},
Bram Moolenaar186628f2013-03-19 13:33:23 +01007755 {"TextChanged", EVENT_TEXTCHANGED},
7756 {"TextChangedI", EVENT_TEXTCHANGEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007757 {"User", EVENT_USER},
7758 {"VimEnter", EVENT_VIMENTER},
7759 {"VimLeave", EVENT_VIMLEAVE},
7760 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7761 {"WinEnter", EVENT_WINENTER},
7762 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007763 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007764 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007765};
7766
7767static AutoPat *first_autopat[NUM_EVENTS] =
7768{
7769 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7770 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7771 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7772 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007773 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7774 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007775};
7776
7777/*
7778 * struct used to keep status while executing autocommands for an event.
7779 */
7780typedef struct AutoPatCmd
7781{
7782 AutoPat *curpat; /* next AutoPat to examine */
7783 AutoCmd *nextcmd; /* next AutoCmd to execute */
7784 int group; /* group being used */
7785 char_u *fname; /* fname to match with */
7786 char_u *sfname; /* sfname to match with */
7787 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007788 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007789 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7790 buf is deleted */
7791 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007792} AutoPatCmd;
7793
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007794static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007795
Bram Moolenaar071d4272004-06-13 20:20:40 +00007796/*
7797 * augroups stores a list of autocmd group names.
7798 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007799static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007800#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7801
7802/*
7803 * The ID of the current group. Group 0 is the default one.
7804 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007805static int current_augroup = AUGROUP_DEFAULT;
7806
7807static int au_need_clean = FALSE; /* need to delete marked patterns */
7808
Bram Moolenaar754b5602006-02-09 23:53:20 +00007809static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007810static void au_remove_pat __ARGS((AutoPat *ap));
7811static void au_remove_cmds __ARGS((AutoPat *ap));
7812static void au_cleanup __ARGS((void));
7813static int au_new_group __ARGS((char_u *name));
7814static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007815static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7816static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007817static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007818static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007819static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007820static int do_autocmd_event __ARGS((event_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007821static int apply_autocmds_group __ARGS((event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007822static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7823
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007824
Bram Moolenaar754b5602006-02-09 23:53:20 +00007825static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007826static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007827static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007828
7829/*
7830 * Show the autocommands for one AutoPat.
7831 */
7832 static void
7833show_autocmd(ap, event)
7834 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007835 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007836{
7837 AutoCmd *ac;
7838
7839 /* Check for "got_int" (here and at various places below), which is set
7840 * when "q" has been hit for the "--more--" prompt */
7841 if (got_int)
7842 return;
7843 if (ap->pat == NULL) /* pattern has been removed */
7844 return;
7845
7846 msg_putchar('\n');
7847 if (got_int)
7848 return;
7849 if (event != last_event || ap->group != last_group)
7850 {
7851 if (ap->group != AUGROUP_DEFAULT)
7852 {
7853 if (AUGROUP_NAME(ap->group) == NULL)
7854 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7855 else
7856 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7857 msg_puts((char_u *)" ");
7858 }
7859 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7860 last_event = event;
7861 last_group = ap->group;
7862 msg_putchar('\n');
7863 if (got_int)
7864 return;
7865 }
7866 msg_col = 4;
7867 msg_outtrans(ap->pat);
7868
7869 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7870 {
7871 if (ac->cmd != NULL) /* skip removed commands */
7872 {
7873 if (msg_col >= 14)
7874 msg_putchar('\n');
7875 msg_col = 14;
7876 if (got_int)
7877 return;
7878 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007879#ifdef FEAT_EVAL
7880 if (p_verbose > 0)
7881 last_set_msg(ac->scriptID);
7882#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007883 if (got_int)
7884 return;
7885 if (ac->next != NULL)
7886 {
7887 msg_putchar('\n');
7888 if (got_int)
7889 return;
7890 }
7891 }
7892 }
7893}
7894
7895/*
7896 * Mark an autocommand pattern for deletion.
7897 */
7898 static void
7899au_remove_pat(ap)
7900 AutoPat *ap;
7901{
7902 vim_free(ap->pat);
7903 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007904 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007905 au_need_clean = TRUE;
7906}
7907
7908/*
7909 * Mark all commands for a pattern for deletion.
7910 */
7911 static void
7912au_remove_cmds(ap)
7913 AutoPat *ap;
7914{
7915 AutoCmd *ac;
7916
7917 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7918 {
7919 vim_free(ac->cmd);
7920 ac->cmd = NULL;
7921 }
7922 au_need_clean = TRUE;
7923}
7924
7925/*
7926 * Cleanup autocommands and patterns that have been deleted.
7927 * This is only done when not executing autocommands.
7928 */
7929 static void
7930au_cleanup()
7931{
7932 AutoPat *ap, **prev_ap;
7933 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007934 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007935
7936 if (autocmd_busy || !au_need_clean)
7937 return;
7938
7939 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007940 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7941 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942 {
7943 /* loop over all autocommand patterns */
7944 prev_ap = &(first_autopat[(int)event]);
7945 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7946 {
7947 /* loop over all commands for this pattern */
7948 prev_ac = &(ap->cmds);
7949 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7950 {
7951 /* remove the command if the pattern is to be deleted or when
7952 * the command has been marked for deletion */
7953 if (ap->pat == NULL || ac->cmd == NULL)
7954 {
7955 *prev_ac = ac->next;
7956 vim_free(ac->cmd);
7957 vim_free(ac);
7958 }
7959 else
7960 prev_ac = &(ac->next);
7961 }
7962
7963 /* remove the pattern if it has been marked for deletion */
7964 if (ap->pat == NULL)
7965 {
7966 *prev_ap = ap->next;
Bram Moolenaar473de612013-06-08 18:19:48 +02007967 vim_regfree(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007968 vim_free(ap);
7969 }
7970 else
7971 prev_ap = &(ap->next);
7972 }
7973 }
7974
7975 au_need_clean = FALSE;
7976}
7977
7978/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007979 * Called when buffer is freed, to remove/invalidate related buffer-local
7980 * autocmds.
7981 */
7982 void
7983aubuflocal_remove(buf)
7984 buf_T *buf;
7985{
7986 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007987 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007988 AutoPatCmd *apc;
7989
7990 /* invalidate currently executing autocommands */
7991 for (apc = active_apc_list; apc; apc = apc->next)
7992 if (buf->b_fnum == apc->arg_bufnr)
7993 apc->arg_bufnr = 0;
7994
7995 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007996 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7997 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007998 /* loop over all autocommand patterns */
7999 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8000 if (ap->buflocal_nr == buf->b_fnum)
8001 {
8002 au_remove_pat(ap);
8003 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008004 {
8005 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008006 smsg((char_u *)
8007 _("auto-removing autocommand: %s <buffer=%d>"),
8008 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008009 verbose_leave();
8010 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008011 }
8012 au_cleanup();
8013}
8014
8015/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008016 * Add an autocmd group name.
8017 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8018 */
8019 static int
8020au_new_group(name)
8021 char_u *name;
8022{
8023 int i;
8024
8025 i = au_find_group(name);
8026 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
8027 {
8028 /* First try using a free entry. */
8029 for (i = 0; i < augroups.ga_len; ++i)
8030 if (AUGROUP_NAME(i) == NULL)
8031 break;
8032 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
8033 return AUGROUP_ERROR;
8034
8035 AUGROUP_NAME(i) = vim_strsave(name);
8036 if (AUGROUP_NAME(i) == NULL)
8037 return AUGROUP_ERROR;
8038 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008039 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008040 }
8041
8042 return i;
8043}
8044
8045 static void
8046au_del_group(name)
8047 char_u *name;
8048{
8049 int i;
8050
8051 i = au_find_group(name);
8052 if (i == AUGROUP_ERROR) /* the group doesn't exist */
8053 EMSG2(_("E367: No such group: \"%s\""), name);
8054 else
8055 {
8056 vim_free(AUGROUP_NAME(i));
8057 AUGROUP_NAME(i) = NULL;
8058 }
8059}
8060
8061/*
8062 * Find the ID of an autocmd group name.
8063 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8064 */
8065 static int
8066au_find_group(name)
8067 char_u *name;
8068{
8069 int i;
8070
8071 for (i = 0; i < augroups.ga_len; ++i)
8072 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
8073 return i;
8074 return AUGROUP_ERROR;
8075}
8076
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008077/*
8078 * Return TRUE if augroup "name" exists.
8079 */
8080 int
8081au_has_group(name)
8082 char_u *name;
8083{
8084 return au_find_group(name) != AUGROUP_ERROR;
8085}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008086
Bram Moolenaar071d4272004-06-13 20:20:40 +00008087/*
8088 * ":augroup {name}".
8089 */
8090 void
8091do_augroup(arg, del_group)
8092 char_u *arg;
8093 int del_group;
8094{
8095 int i;
8096
8097 if (del_group)
8098 {
8099 if (*arg == NUL)
8100 EMSG(_(e_argreq));
8101 else
8102 au_del_group(arg);
8103 }
8104 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
8105 current_augroup = AUGROUP_DEFAULT;
8106 else if (*arg) /* ":aug xxx": switch to group xxx */
8107 {
8108 i = au_new_group(arg);
8109 if (i != AUGROUP_ERROR)
8110 current_augroup = i;
8111 }
8112 else /* ":aug": list the group names */
8113 {
8114 msg_start();
8115 for (i = 0; i < augroups.ga_len; ++i)
8116 {
8117 if (AUGROUP_NAME(i) != NULL)
8118 {
8119 msg_puts(AUGROUP_NAME(i));
8120 msg_puts((char_u *)" ");
8121 }
8122 }
8123 msg_clr_eos();
8124 msg_end();
8125 }
8126}
8127
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008128#if defined(EXITFREE) || defined(PROTO)
8129 void
8130free_all_autocmds()
8131{
8132 for (current_augroup = -1; current_augroup < augroups.ga_len;
8133 ++current_augroup)
8134 do_autocmd((char_u *)"", TRUE);
8135 ga_clear_strings(&augroups);
8136}
8137#endif
8138
Bram Moolenaar071d4272004-06-13 20:20:40 +00008139/*
8140 * Return the event number for event name "start".
8141 * Return NUM_EVENTS if the event name was not found.
8142 * Return a pointer to the next event name in "end".
8143 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008144 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00008145event_name2nr(start, end)
8146 char_u *start;
8147 char_u **end;
8148{
8149 char_u *p;
8150 int i;
8151 int len;
8152
8153 /* the event name ends with end of line, a blank or a comma */
8154 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
8155 ;
8156 for (i = 0; event_names[i].name != NULL; ++i)
8157 {
8158 len = (int)STRLEN(event_names[i].name);
8159 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
8160 break;
8161 }
8162 if (*p == ',')
8163 ++p;
8164 *end = p;
8165 if (event_names[i].name == NULL)
8166 return NUM_EVENTS;
8167 return event_names[i].event;
8168}
8169
8170/*
8171 * Return the name for event "event".
8172 */
8173 static char_u *
8174event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008175 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008176{
8177 int i;
8178
8179 for (i = 0; event_names[i].name != NULL; ++i)
8180 if (event_names[i].event == event)
8181 return (char_u *)event_names[i].name;
8182 return (char_u *)"Unknown";
8183}
8184
8185/*
8186 * Scan over the events. "*" stands for all events.
8187 */
8188 static char_u *
8189find_end_event(arg, have_group)
8190 char_u *arg;
8191 int have_group; /* TRUE when group name was found */
8192{
8193 char_u *pat;
8194 char_u *p;
8195
8196 if (*arg == '*')
8197 {
8198 if (arg[1] && !vim_iswhite(arg[1]))
8199 {
8200 EMSG2(_("E215: Illegal character after *: %s"), arg);
8201 return NULL;
8202 }
8203 pat = arg + 1;
8204 }
8205 else
8206 {
8207 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
8208 {
8209 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
8210 {
8211 if (have_group)
8212 EMSG2(_("E216: No such event: %s"), pat);
8213 else
8214 EMSG2(_("E216: No such group or event: %s"), pat);
8215 return NULL;
8216 }
8217 }
8218 }
8219 return pat;
8220}
8221
8222/*
8223 * Return TRUE if "event" is included in 'eventignore'.
8224 */
8225 static int
8226event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008227 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228{
8229 char_u *p = p_ei;
8230
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008231 while (*p != NUL)
8232 {
8233 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8234 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008235 if (event_name2nr(p, &p) == event)
8236 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008237 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008238
8239 return FALSE;
8240}
8241
8242/*
8243 * Return OK when the contents of p_ei is valid, FAIL otherwise.
8244 */
8245 int
8246check_ei()
8247{
8248 char_u *p = p_ei;
8249
Bram Moolenaar071d4272004-06-13 20:20:40 +00008250 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008251 {
8252 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8253 {
8254 p += 3;
8255 if (*p == ',')
8256 ++p;
8257 }
8258 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008259 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008260 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008261
8262 return OK;
8263}
8264
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008265# if defined(FEAT_SYN_HL) || defined(PROTO)
8266
8267/*
8268 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
8269 * buffer loaded into the window. "what" must start with a comma.
8270 * Returns the old value of 'eventignore' in allocated memory.
8271 */
8272 char_u *
8273au_event_disable(what)
8274 char *what;
8275{
8276 char_u *new_ei;
8277 char_u *save_ei;
8278
8279 save_ei = vim_strsave(p_ei);
8280 if (save_ei != NULL)
8281 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008282 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008283 if (new_ei != NULL)
8284 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008285 if (*what == ',' && *p_ei == NUL)
8286 STRCPY(new_ei, what + 1);
8287 else
8288 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008289 set_string_option_direct((char_u *)"ei", -1, new_ei,
8290 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008291 vim_free(new_ei);
8292 }
8293 }
8294 return save_ei;
8295}
8296
8297 void
8298au_event_restore(old_ei)
8299 char_u *old_ei;
8300{
8301 if (old_ei != NULL)
8302 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008303 set_string_option_direct((char_u *)"ei", -1, old_ei,
8304 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008305 vim_free(old_ei);
8306 }
8307}
8308# endif /* FEAT_SYN_HL */
8309
Bram Moolenaar071d4272004-06-13 20:20:40 +00008310/*
8311 * do_autocmd() -- implements the :autocmd command. Can be used in the
8312 * following ways:
8313 *
8314 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8315 * will be automatically executed for <event>
8316 * when editing a file matching <pat>, in
8317 * the current group.
8318 * :autocmd <event> <pat> Show the auto-commands associated with
8319 * <event> and <pat>.
8320 * :autocmd <event> Show the auto-commands associated with
8321 * <event>.
8322 * :autocmd Show all auto-commands.
8323 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
8324 * <event> and <pat>, and add the command
8325 * <cmd>, for the current group.
8326 * :autocmd! <event> <pat> Remove all auto-commands associated with
8327 * <event> and <pat> for the current group.
8328 * :autocmd! <event> Remove all auto-commands associated with
8329 * <event> for the current group.
8330 * :autocmd! Remove ALL auto-commands for the current
8331 * group.
8332 *
8333 * Multiple events and patterns may be given separated by commas. Here are
8334 * some examples:
8335 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8336 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8337 *
8338 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008339 *
8340 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008341 */
8342 void
8343do_autocmd(arg, forceit)
8344 char_u *arg;
8345 int forceit;
8346{
8347 char_u *pat;
8348 char_u *envpat = NULL;
8349 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008350 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008351 int need_free = FALSE;
8352 int nested = FALSE;
8353 int group;
8354
8355 /*
8356 * Check for a legal group name. If not, use AUGROUP_ALL.
8357 */
8358 group = au_get_grouparg(&arg);
8359 if (arg == NULL) /* out of memory */
8360 return;
8361
8362 /*
8363 * Scan over the events.
8364 * If we find an illegal name, return here, don't do anything.
8365 */
8366 pat = find_end_event(arg, group != AUGROUP_ALL);
8367 if (pat == NULL)
8368 return;
8369
8370 /*
8371 * Scan over the pattern. Put a NUL at the end.
8372 */
8373 pat = skipwhite(pat);
8374 cmd = pat;
8375 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
8376 cmd++;
8377 if (*cmd)
8378 *cmd++ = NUL;
8379
8380 /* Expand environment variables in the pattern. Set 'shellslash', we want
8381 * forward slashes here. */
8382 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8383 {
8384#ifdef BACKSLASH_IN_FILENAME
8385 int p_ssl_save = p_ssl;
8386
8387 p_ssl = TRUE;
8388#endif
8389 envpat = expand_env_save(pat);
8390#ifdef BACKSLASH_IN_FILENAME
8391 p_ssl = p_ssl_save;
8392#endif
8393 if (envpat != NULL)
8394 pat = envpat;
8395 }
8396
8397 /*
8398 * Check for "nested" flag.
8399 */
8400 cmd = skipwhite(cmd);
8401 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
8402 {
8403 nested = TRUE;
8404 cmd = skipwhite(cmd + 6);
8405 }
8406
8407 /*
8408 * Find the start of the commands.
8409 * Expand <sfile> in it.
8410 */
8411 if (*cmd != NUL)
8412 {
8413 cmd = expand_sfile(cmd);
8414 if (cmd == NULL) /* some error */
8415 return;
8416 need_free = TRUE;
8417 }
8418
8419 /*
8420 * Print header when showing autocommands.
8421 */
8422 if (!forceit && *cmd == NUL)
8423 {
8424 /* Highlight title */
8425 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
8426 }
8427
8428 /*
8429 * Loop over the events.
8430 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008431 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008432 last_group = AUGROUP_ERROR; /* for listing the group name */
8433 if (*arg == '*' || *arg == NUL)
8434 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008435 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8436 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008437 if (do_autocmd_event(event, pat,
8438 nested, cmd, forceit, group) == FAIL)
8439 break;
8440 }
8441 else
8442 {
8443 while (*arg && !vim_iswhite(*arg))
8444 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8445 nested, cmd, forceit, group) == FAIL)
8446 break;
8447 }
8448
8449 if (need_free)
8450 vim_free(cmd);
8451 vim_free(envpat);
8452}
8453
8454/*
8455 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8456 * The "argp" argument is advanced to the following argument.
8457 *
8458 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8459 */
8460 static int
8461au_get_grouparg(argp)
8462 char_u **argp;
8463{
8464 char_u *group_name;
8465 char_u *p;
8466 char_u *arg = *argp;
8467 int group = AUGROUP_ALL;
8468
8469 p = skiptowhite(arg);
8470 if (p > arg)
8471 {
8472 group_name = vim_strnsave(arg, (int)(p - arg));
8473 if (group_name == NULL) /* out of memory */
8474 return AUGROUP_ERROR;
8475 group = au_find_group(group_name);
8476 if (group == AUGROUP_ERROR)
8477 group = AUGROUP_ALL; /* no match, use all groups */
8478 else
8479 *argp = skipwhite(p); /* match, skip over group name */
8480 vim_free(group_name);
8481 }
8482 return group;
8483}
8484
8485/*
8486 * do_autocmd() for one event.
8487 * If *pat == NUL do for all patterns.
8488 * If *cmd == NUL show entries.
8489 * If forceit == TRUE delete entries.
8490 * If group is not AUGROUP_ALL, only use this group.
8491 */
8492 static int
8493do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008494 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008495 char_u *pat;
8496 int nested;
8497 char_u *cmd;
8498 int forceit;
8499 int group;
8500{
8501 AutoPat *ap;
8502 AutoPat **prev_ap;
8503 AutoCmd *ac;
8504 AutoCmd **prev_ac;
8505 int brace_level;
8506 char_u *endpat;
8507 int findgroup;
8508 int allgroups;
8509 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008510 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008511 int buflocal_nr;
8512 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008513
8514 if (group == AUGROUP_ALL)
8515 findgroup = current_augroup;
8516 else
8517 findgroup = group;
8518 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8519
8520 /*
8521 * Show or delete all patterns for an event.
8522 */
8523 if (*pat == NUL)
8524 {
8525 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8526 {
8527 if (forceit) /* delete the AutoPat, if it's in the current group */
8528 {
8529 if (ap->group == findgroup)
8530 au_remove_pat(ap);
8531 }
8532 else if (group == AUGROUP_ALL || ap->group == group)
8533 show_autocmd(ap, event);
8534 }
8535 }
8536
8537 /*
8538 * Loop through all the specified patterns.
8539 */
8540 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8541 {
8542 /*
8543 * Find end of the pattern.
8544 * Watch out for a comma in braces, like "*.\{obj,o\}".
8545 */
8546 brace_level = 0;
8547 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
8548 || endpat[-1] == '\\'); ++endpat)
8549 {
8550 if (*endpat == '{')
8551 brace_level++;
8552 else if (*endpat == '}')
8553 brace_level--;
8554 }
8555 if (pat == endpat) /* ignore single comma */
8556 continue;
8557 patlen = (int)(endpat - pat);
8558
8559 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008560 * detect special <buflocal[=X]> buffer-local patterns
8561 */
8562 is_buflocal = FALSE;
8563 buflocal_nr = 0;
8564
8565 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
8566 && pat[patlen - 1] == '>')
8567 {
8568 /* Error will be printed only for addition. printing and removing
8569 * will proceed silently. */
8570 is_buflocal = TRUE;
8571 if (patlen == 8)
8572 buflocal_nr = curbuf->b_fnum;
8573 else if (patlen > 9 && pat[7] == '=')
8574 {
8575 /* <buffer=abuf> */
8576 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
8577 buflocal_nr = autocmd_bufnr;
8578 /* <buffer=123> */
8579 else if (skipdigits(pat + 8) == pat + patlen - 1)
8580 buflocal_nr = atoi((char *)pat + 8);
8581 }
8582 }
8583
8584 if (is_buflocal)
8585 {
8586 /* normalize pat into standard "<buffer>#N" form */
8587 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8588 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008589 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008590 }
8591
8592 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008593 * Find AutoPat entries with this pattern.
8594 */
8595 prev_ap = &first_autopat[(int)event];
8596 while ((ap = *prev_ap) != NULL)
8597 {
8598 if (ap->pat != NULL)
8599 {
8600 /* Accept a pattern when:
8601 * - a group was specified and it's that group, or a group was
8602 * not specified and it's the current group, or a group was
8603 * not specified and we are listing
8604 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008605 * - the pattern matches.
8606 * For <buffer[=X]>, this condition works because we normalize
8607 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008608 */
8609 if ((allgroups || ap->group == findgroup)
8610 && ap->patlen == patlen
8611 && STRNCMP(pat, ap->pat, patlen) == 0)
8612 {
8613 /*
8614 * Remove existing autocommands.
8615 * If adding any new autocmd's for this AutoPat, don't
8616 * delete the pattern from the autopat list, append to
8617 * this list.
8618 */
8619 if (forceit)
8620 {
8621 if (*cmd != NUL && ap->next == NULL)
8622 {
8623 au_remove_cmds(ap);
8624 break;
8625 }
8626 au_remove_pat(ap);
8627 }
8628
8629 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008630 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008631 */
8632 else if (*cmd == NUL)
8633 show_autocmd(ap, event);
8634
8635 /*
8636 * Add autocmd to this autopat, if it's the last one.
8637 */
8638 else if (ap->next == NULL)
8639 break;
8640 }
8641 }
8642 prev_ap = &ap->next;
8643 }
8644
8645 /*
8646 * Add a new command.
8647 */
8648 if (*cmd != NUL)
8649 {
8650 /*
8651 * If the pattern we want to add a command to does appear at the
8652 * end of the list (or not is not in the list at all), add the
8653 * pattern at the end of the list.
8654 */
8655 if (ap == NULL)
8656 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008657 /* refuse to add buffer-local ap if buffer number is invalid */
8658 if (is_buflocal && (buflocal_nr == 0
8659 || buflist_findnr(buflocal_nr) == NULL))
8660 {
8661 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
8662 buflocal_nr);
8663 return FAIL;
8664 }
8665
Bram Moolenaar071d4272004-06-13 20:20:40 +00008666 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8667 if (ap == NULL)
8668 return FAIL;
8669 ap->pat = vim_strnsave(pat, patlen);
8670 ap->patlen = patlen;
8671 if (ap->pat == NULL)
8672 {
8673 vim_free(ap);
8674 return FAIL;
8675 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008676
8677 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008678 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008679 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008680 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008681 }
8682 else
8683 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008684 char_u *reg_pat;
8685
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008686 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008687 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008688 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008689 if (reg_pat != NULL)
8690 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008691 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008692 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008693 {
8694 vim_free(ap->pat);
8695 vim_free(ap);
8696 return FAIL;
8697 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008698 }
8699 ap->cmds = NULL;
8700 *prev_ap = ap;
8701 ap->next = NULL;
8702 if (group == AUGROUP_ALL)
8703 ap->group = current_augroup;
8704 else
8705 ap->group = group;
8706 }
8707
8708 /*
8709 * Add the autocmd at the end of the AutoCmd list.
8710 */
8711 prev_ac = &(ap->cmds);
8712 while ((ac = *prev_ac) != NULL)
8713 prev_ac = &ac->next;
8714 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8715 if (ac == NULL)
8716 return FAIL;
8717 ac->cmd = vim_strsave(cmd);
8718#ifdef FEAT_EVAL
8719 ac->scriptID = current_SID;
8720#endif
8721 if (ac->cmd == NULL)
8722 {
8723 vim_free(ac);
8724 return FAIL;
8725 }
8726 ac->next = NULL;
8727 *prev_ac = ac;
8728 ac->nested = nested;
8729 }
8730 }
8731
8732 au_cleanup(); /* may really delete removed patterns/commands now */
8733 return OK;
8734}
8735
8736/*
8737 * Implementation of ":doautocmd [group] event [fname]".
8738 * Return OK for success, FAIL for failure;
8739 */
8740 int
8741do_doautocmd(arg, do_msg)
8742 char_u *arg;
8743 int do_msg; /* give message for no matching autocmds? */
8744{
8745 char_u *fname;
8746 int nothing_done = TRUE;
8747 int group;
8748
8749 /*
8750 * Check for a legal group name. If not, use AUGROUP_ALL.
8751 */
8752 group = au_get_grouparg(&arg);
8753 if (arg == NULL) /* out of memory */
8754 return FAIL;
8755
8756 if (*arg == '*')
8757 {
8758 EMSG(_("E217: Can't execute autocommands for ALL events"));
8759 return FAIL;
8760 }
8761
8762 /*
8763 * Scan over the events.
8764 * If we find an illegal name, return here, don't do anything.
8765 */
8766 fname = find_end_event(arg, group != AUGROUP_ALL);
8767 if (fname == NULL)
8768 return FAIL;
8769
8770 fname = skipwhite(fname);
8771
8772 /*
8773 * Loop over the events.
8774 */
8775 while (*arg && !vim_iswhite(*arg))
8776 if (apply_autocmds_group(event_name2nr(arg, &arg),
8777 fname, NULL, TRUE, group, curbuf, NULL))
8778 nothing_done = FALSE;
8779
8780 if (nothing_done && do_msg)
8781 MSG(_("No matching autocommands"));
8782
8783#ifdef FEAT_EVAL
8784 return aborting() ? FAIL : OK;
8785#else
8786 return OK;
8787#endif
8788}
8789
8790/*
8791 * ":doautoall": execute autocommands for each loaded buffer.
8792 */
8793 void
8794ex_doautoall(eap)
8795 exarg_T *eap;
8796{
8797 int retval;
8798 aco_save_T aco;
8799 buf_T *buf;
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008800 char_u *arg = eap->arg;
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008801 int call_do_modelines = check_nomodeline(&arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008802
8803 /*
8804 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8805 * equal to curbuf, but for some buffers there may not be a window.
8806 * So we change the buffer for the current window for a moment. This
8807 * gives problems when the autocommands make changes to the list of
8808 * buffers or windows...
8809 */
8810 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8811 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008812 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008813 {
8814 /* find a window for this buffer and save some values */
8815 aucmd_prepbuf(&aco, buf);
8816
8817 /* execute the autocommands for this buffer */
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008818 retval = do_doautocmd(arg, FALSE);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008819
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008820 if (call_do_modelines)
8821 {
8822 /* Execute the modeline settings, but don't set window-local
8823 * options if we are using the current window for another
8824 * buffer. */
8825 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
8826 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008827
8828 /* restore the current window */
8829 aucmd_restbuf(&aco);
8830
8831 /* stop if there is some error or buffer was deleted */
8832 if (retval == FAIL || !buf_valid(buf))
8833 break;
8834 }
8835 }
8836
8837 check_cursor(); /* just in case lines got deleted */
8838}
8839
8840/*
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008841 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
8842 * return TRUE and advance *argp to after it.
8843 * Thus return TRUE when do_modelines() should be called.
8844 */
8845 int
8846check_nomodeline(argp)
8847 char_u **argp;
8848{
8849 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
8850 {
8851 *argp = skipwhite(*argp + 12);
8852 return FALSE;
8853 }
8854 return TRUE;
8855}
8856
8857/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008858 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008859 * Search for a visible window containing the current buffer. If there isn't
8860 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008861 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008862 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008863 */
8864 void
8865aucmd_prepbuf(aco, buf)
8866 aco_save_T *aco; /* structure to save values in */
8867 buf_T *buf; /* new curbuf */
8868{
8869 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008870#ifdef FEAT_WINDOWS
8871 int save_ea;
8872#endif
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008873#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008874 int save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008875#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008876
8877 /* Find a window that is for the new buffer */
8878 if (buf == curbuf) /* be quick when buf is curbuf */
8879 win = curwin;
8880 else
8881#ifdef FEAT_WINDOWS
8882 for (win = firstwin; win != NULL; win = win->w_next)
8883 if (win->w_buffer == buf)
8884 break;
8885#else
8886 win = NULL;
8887#endif
8888
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008889 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
8890 * back to using the current window. */
8891 if (win == NULL && aucmd_win == NULL)
8892 {
8893 win_alloc_aucmd_win();
8894 if (aucmd_win == NULL)
8895 win = curwin;
8896 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008897 if (win == NULL && aucmd_win_used)
8898 /* Strange recursive autocommand, fall back to using the current
8899 * window. Expect a few side effects... */
8900 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008901
8902 aco->save_curwin = curwin;
8903 aco->save_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008904 if (win != NULL)
8905 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008906 /* There is a window for "buf" in the current tab page, make it the
8907 * curwin. This is preferred, it has the least side effects (esp. if
8908 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008909 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008910 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008911 }
8912 else
8913 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008914 /* There is no window for "buf", use "aucmd_win". To minimize the side
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02008915 * effects, insert it in the current tab page.
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008916 * Anything related to a window (e.g., setting folds) may have
8917 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008918 aco->use_aucmd_win = TRUE;
8919 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008920 aucmd_win->w_buffer = buf;
Bram Moolenaarcdddaa42010-06-07 23:07:44 +02008921 aucmd_win->w_s = &buf->b_s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008922 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008923 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008924
8925 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
8926 * win_enter_ext(). */
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008927 vim_free(aucmd_win->w_localdir);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008928 aucmd_win->w_localdir = NULL;
8929 aco->globaldir = globaldir;
8930 globaldir = NULL;
8931
Bram Moolenaar071d4272004-06-13 20:20:40 +00008932
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008933#ifdef FEAT_WINDOWS
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008934 /* Split the current window, put the aucmd_win in the upper half.
8935 * We don't want the BufEnter or WinEnter autocommands. */
8936 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008937 make_snapshot(SNAP_AUCMD_IDX);
8938 save_ea = p_ea;
8939 p_ea = FALSE;
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008940
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008941# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008942 /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
8943 save_acd = p_acd;
8944 p_acd = FALSE;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008945# endif
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008946
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008947 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
8948 (void)win_comp_pos(); /* recompute window positions */
8949 p_ea = save_ea;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008950# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008951 p_acd = save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008952# endif
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008953 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008954#endif
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008955 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008956 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008958 aco->new_curwin = curwin;
8959 aco->new_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008960}
8961
8962/*
8963 * Cleanup after executing autocommands for a (hidden) buffer.
8964 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008965 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008966 */
8967 void
8968aucmd_restbuf(aco)
8969 aco_save_T *aco; /* structure holding saved values */
8970{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008971#ifdef FEAT_WINDOWS
8972 int dummy;
8973#endif
8974
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008975 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008976 {
8977 --curbuf->b_nwindows;
8978#ifdef FEAT_WINDOWS
8979 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008980 * page. Do not trigger autocommands here. */
8981 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008982 if (curwin != aucmd_win)
8983 {
8984 tabpage_T *tp;
8985 win_T *wp;
8986
8987 FOR_ALL_TAB_WINDOWS(tp, wp)
8988 {
8989 if (wp == aucmd_win)
8990 {
8991 if (tp != curtab)
Bram Moolenaar49e649f2013-05-06 04:50:35 +02008992 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008993 win_goto(aucmd_win);
Bram Moolenaar28f29082012-02-11 23:45:37 +01008994 goto win_found;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008995 }
8996 }
8997 }
Bram Moolenaar28f29082012-02-11 23:45:37 +01008998win_found:
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008999
9000 /* Remove the window and frame from the tree of frames. */
9001 (void)winframe_remove(curwin, &dummy, NULL);
9002 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009003 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009004 last_status(FALSE); /* may need to remove last status line */
9005 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
9006 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009007 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009008
9009 if (win_valid(aco->save_curwin))
9010 curwin = aco->save_curwin;
9011 else
9012 /* Hmm, original window disappeared. Just use the first one. */
9013 curwin = firstwin;
9014# ifdef FEAT_EVAL
Bram Moolenaar429fa852013-04-15 12:27:36 +02009015 vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
9016 hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009017# endif
9018#else
9019 curwin = aco->save_curwin;
9020#endif
9021 curbuf = curwin->w_buffer;
9022
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009023 vim_free(globaldir);
9024 globaldir = aco->globaldir;
9025
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009026 /* the buffer contents may have changed */
9027 check_cursor();
9028 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
9029 {
9030 curwin->w_topline = curbuf->b_ml.ml_line_count;
9031#ifdef FEAT_DIFF
9032 curwin->w_topfill = 0;
9033#endif
9034 }
9035#if defined(FEAT_GUI)
9036 /* Hide the scrollbars from the aucmd_win and update. */
9037 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
9038 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
9039 gui_may_update_scrollbars();
9040#endif
9041 }
9042 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009043 {
9044 /* restore curwin */
9045#ifdef FEAT_WINDOWS
9046 if (win_valid(aco->save_curwin))
9047#endif
9048 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009049 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009050 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009051 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009052 if (curwin == aco->new_curwin
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009053 && curbuf != aco->new_curbuf
9054 && buf_valid(aco->new_curbuf)
9055 && aco->new_curbuf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009056 {
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009057# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
9058 if (curwin->w_s == &curbuf->b_s)
9059 curwin->w_s = &aco->new_curbuf->b_s;
9060# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009061 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009062 curbuf = aco->new_curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009063 curwin->w_buffer = curbuf;
9064 ++curbuf->b_nwindows;
9065 }
9066
9067 curwin = aco->save_curwin;
9068 curbuf = curwin->w_buffer;
9069 }
9070 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009071}
9072
9073static int autocmd_nested = FALSE;
9074
9075/*
9076 * Execute autocommands for "event" and file name "fname".
9077 * Return TRUE if some commands were executed.
9078 */
9079 int
9080apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009081 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009082 char_u *fname; /* NULL or empty means use actual file name */
9083 char_u *fname_io; /* fname to use for <afile> on cmdline */
9084 int force; /* when TRUE, ignore autocmd_busy */
9085 buf_T *buf; /* buffer for <abuf> */
9086{
9087 return apply_autocmds_group(event, fname, fname_io, force,
9088 AUGROUP_ALL, buf, NULL);
9089}
9090
9091/*
9092 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
9093 * setting v:filearg.
9094 */
9095 static int
9096apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009097 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009098 char_u *fname;
9099 char_u *fname_io;
9100 int force;
9101 buf_T *buf;
9102 exarg_T *eap;
9103{
9104 return apply_autocmds_group(event, fname, fname_io, force,
9105 AUGROUP_ALL, buf, eap);
9106}
9107
9108/*
9109 * Like apply_autocmds(), but handles the caller's retval. If the script
9110 * processing is being aborted or if retval is FAIL when inside a try
9111 * conditional, no autocommands are executed. If otherwise the autocommands
9112 * cause the script to be aborted, retval is set to FAIL.
9113 */
9114 int
9115apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009116 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009117 char_u *fname; /* NULL or empty means use actual file name */
9118 char_u *fname_io; /* fname to use for <afile> on cmdline */
9119 int force; /* when TRUE, ignore autocmd_busy */
9120 buf_T *buf; /* buffer for <abuf> */
9121 int *retval; /* pointer to caller's retval */
9122{
9123 int did_cmd;
9124
Bram Moolenaar1e015462005-09-25 22:16:38 +00009125#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009126 if (should_abort(*retval))
9127 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00009128#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009129
9130 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
9131 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00009132 if (did_cmd
9133#ifdef FEAT_EVAL
9134 && aborting()
9135#endif
9136 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00009137 *retval = FAIL;
9138 return did_cmd;
9139}
9140
Bram Moolenaard35f9712005-12-18 22:02:33 +00009141/*
9142 * Return TRUE when there is a CursorHold autocommand defined.
9143 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009144 int
9145has_cursorhold()
9146{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009147 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
9148 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009149}
Bram Moolenaard35f9712005-12-18 22:02:33 +00009150
9151/*
9152 * Return TRUE if the CursorHold event can be triggered.
9153 */
9154 int
9155trigger_cursorhold()
9156{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009157 int state;
9158
Bram Moolenaar05334432011-07-20 18:29:39 +02009159 if (!did_cursorhold
9160 && has_cursorhold()
9161 && !Recording
9162 && typebuf.tb_len == 0
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00009163#ifdef FEAT_INS_EXPAND
9164 && !ins_compl_active()
9165#endif
9166 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00009167 {
9168 state = get_real_state();
9169 if (state == NORMAL_BUSY || (state & INSERT) != 0)
9170 return TRUE;
9171 }
9172 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00009173}
Bram Moolenaar754b5602006-02-09 23:53:20 +00009174
9175/*
9176 * Return TRUE when there is a CursorMoved autocommand defined.
9177 */
9178 int
9179has_cursormoved()
9180{
9181 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
9182}
9183
9184/*
9185 * Return TRUE when there is a CursorMovedI autocommand defined.
9186 */
9187 int
9188has_cursormovedI()
9189{
9190 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
9191}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009192
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009193/*
Bram Moolenaar186628f2013-03-19 13:33:23 +01009194 * Return TRUE when there is a TextChanged autocommand defined.
9195 */
9196 int
9197has_textchanged()
9198{
9199 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
9200}
9201
9202/*
9203 * Return TRUE when there is a TextChangedI autocommand defined.
9204 */
9205 int
9206has_textchangedI()
9207{
9208 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
9209}
9210
9211/*
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009212 * Return TRUE when there is an InsertCharPre autocommand defined.
9213 */
9214 int
9215has_insertcharpre()
9216{
9217 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
9218}
9219
Bram Moolenaar071d4272004-06-13 20:20:40 +00009220 static int
9221apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009222 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009223 char_u *fname; /* NULL or empty means use actual file name */
9224 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
9225 use fname */
9226 int force; /* when TRUE, ignore autocmd_busy */
9227 int group; /* group ID, or AUGROUP_ALL */
9228 buf_T *buf; /* buffer for <abuf> */
9229 exarg_T *eap; /* command arguments */
9230{
9231 char_u *sfname = NULL; /* short file name */
9232 char_u *tail;
9233 int save_changed;
9234 buf_T *old_curbuf;
9235 int retval = FALSE;
9236 char_u *save_sourcing_name;
9237 linenr_T save_sourcing_lnum;
9238 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009239 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009240 int save_autocmd_bufnr;
9241 char_u *save_autocmd_match;
9242 int save_autocmd_busy;
9243 int save_autocmd_nested;
9244 static int nesting = 0;
9245 AutoPatCmd patcmd;
9246 AutoPat *ap;
9247#ifdef FEAT_EVAL
9248 scid_T save_current_SID;
9249 void *save_funccalp;
9250 char_u *save_cmdarg;
9251 long save_cmdbang;
9252#endif
9253 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00009254#ifdef FEAT_PROFILE
9255 proftime_T wait_time;
9256#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009257
9258 /*
9259 * Quickly return if there are no autocommands for this event or
9260 * autocommands are blocked.
9261 */
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009262 if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009263 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009264
9265 /*
9266 * When autocommands are busy, new autocommands are only executed when
9267 * explicitly enabled with the "nested" flag.
9268 */
9269 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009270 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009271
9272#ifdef FEAT_EVAL
9273 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00009274 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00009275 * occurred or an exception was thrown but not caught.
9276 */
9277 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009278 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009279#endif
9280
9281 /*
9282 * FileChangedShell never nests, because it can create an endless loop.
9283 */
Bram Moolenaar56718732006-03-15 22:53:57 +00009284 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
9285 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009286 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009287
9288 /*
9289 * Ignore events in 'eventignore'.
9290 */
9291 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009292 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009293
9294 /*
9295 * Allow nesting of autocommands, but restrict the depth, because it's
9296 * possible to create an endless loop.
9297 */
9298 if (nesting == 10)
9299 {
9300 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009301 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009302 }
9303
9304 /*
9305 * Check if these autocommands are disabled. Used when doing ":all" or
9306 * ":ball".
9307 */
9308 if ( (autocmd_no_enter
9309 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
9310 || (autocmd_no_leave
9311 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009312 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009313
9314 /*
9315 * Save the autocmd_* variables and info about the current buffer.
9316 */
9317 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009318 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009319 save_autocmd_bufnr = autocmd_bufnr;
9320 save_autocmd_match = autocmd_match;
9321 save_autocmd_busy = autocmd_busy;
9322 save_autocmd_nested = autocmd_nested;
9323 save_changed = curbuf->b_changed;
9324 old_curbuf = curbuf;
9325
9326 /*
9327 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00009328 * Make a copy to avoid that changing a buffer name or directory makes it
9329 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009330 */
9331 if (fname_io == NULL)
9332 {
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009333 if (event == EVENT_COLORSCHEME)
9334 autocmd_fname = NULL;
9335 else if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009336 autocmd_fname = fname;
9337 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009338 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009339 else
9340 autocmd_fname = NULL;
9341 }
9342 else
9343 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009344 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009345 autocmd_fname = vim_strsave(autocmd_fname);
9346 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009347
9348 /*
9349 * Set the buffer number to be used for <abuf>.
9350 */
9351 if (buf == NULL)
9352 autocmd_bufnr = 0;
9353 else
9354 autocmd_bufnr = buf->b_fnum;
9355
9356 /*
9357 * When the file name is NULL or empty, use the file name of buffer "buf".
9358 * Always use the full path of the file name to match with, in case
9359 * "allow_dirs" is set.
9360 */
9361 if (fname == NULL || *fname == NUL)
9362 {
9363 if (buf == NULL)
9364 fname = NULL;
9365 else
9366 {
9367#ifdef FEAT_SYN_HL
9368 if (event == EVENT_SYNTAX)
9369 fname = buf->b_p_syn;
9370 else
9371#endif
9372 if (event == EVENT_FILETYPE)
9373 fname = buf->b_p_ft;
9374 else
9375 {
9376 if (buf->b_sfname != NULL)
9377 sfname = vim_strsave(buf->b_sfname);
9378 fname = buf->b_ffname;
9379 }
9380 }
9381 if (fname == NULL)
9382 fname = (char_u *)"";
9383 fname = vim_strsave(fname); /* make a copy, so we can change it */
9384 }
9385 else
9386 {
9387 sfname = vim_strsave(fname);
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009388 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
9389 * ColorScheme or QuickFixCmd* */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009390 if (event == EVENT_FILETYPE
9391 || event == EVENT_SYNTAX
Bram Moolenaar5135d462009-04-29 16:03:38 +00009392 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009393 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009394 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009395 || event == EVENT_QUICKFIXCMDPRE
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009396 || event == EVENT_COLORSCHEME
Bram Moolenaar7c626922005-02-07 22:01:03 +00009397 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009398 fname = vim_strsave(fname);
9399 else
9400 fname = FullName_save(fname, FALSE);
9401 }
9402 if (fname == NULL) /* out of memory */
9403 {
9404 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009405 retval = FALSE;
9406 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009407 }
9408
9409#ifdef BACKSLASH_IN_FILENAME
9410 /*
9411 * Replace all backslashes with forward slashes. This makes the
9412 * autocommand patterns portable between Unix and MS-DOS.
9413 */
9414 if (sfname != NULL)
9415 forward_slash(sfname);
9416 forward_slash(fname);
9417#endif
9418
9419#ifdef VMS
9420 /* remove version for correct match */
9421 if (sfname != NULL)
9422 vms_remove_version(sfname);
9423 vms_remove_version(fname);
9424#endif
9425
9426 /*
9427 * Set the name to be used for <amatch>.
9428 */
9429 autocmd_match = fname;
9430
9431
9432 /* Don't redraw while doing auto commands. */
9433 ++RedrawingDisabled;
9434 save_sourcing_name = sourcing_name;
9435 sourcing_name = NULL; /* don't free this one */
9436 save_sourcing_lnum = sourcing_lnum;
9437 sourcing_lnum = 0; /* no line number here */
9438
9439#ifdef FEAT_EVAL
9440 save_current_SID = current_SID;
9441
Bram Moolenaar05159a02005-02-26 23:04:13 +00009442# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009443 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009444 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9445# endif
9446
Bram Moolenaar071d4272004-06-13 20:20:40 +00009447 /* Don't use local function variables, if called from a function */
9448 save_funccalp = save_funccal();
9449#endif
9450
9451 /*
9452 * When starting to execute autocommands, save the search patterns.
9453 */
9454 if (!autocmd_busy)
9455 {
9456 save_search_patterns();
9457 saveRedobuff();
9458 did_filetype = keep_filetype;
9459 }
9460
9461 /*
9462 * Note that we are applying autocmds. Some commands need to know.
9463 */
9464 autocmd_busy = TRUE;
9465 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9466 ++nesting; /* see matching decrement below */
9467
9468 /* Remember that FileType was triggered. Used for did_filetype(). */
9469 if (event == EVENT_FILETYPE)
9470 did_filetype = TRUE;
9471
9472 tail = gettail(fname);
9473
9474 /* Find first autocommand that matches */
9475 patcmd.curpat = first_autopat[(int)event];
9476 patcmd.nextcmd = NULL;
9477 patcmd.group = group;
9478 patcmd.fname = fname;
9479 patcmd.sfname = sfname;
9480 patcmd.tail = tail;
9481 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009482 patcmd.arg_bufnr = autocmd_bufnr;
9483 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009484 auto_next_pat(&patcmd, FALSE);
9485
9486 /* found one, start executing the autocommands */
9487 if (patcmd.curpat != NULL)
9488 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009489 /* add to active_apc_list */
9490 patcmd.next = active_apc_list;
9491 active_apc_list = &patcmd;
9492
Bram Moolenaar071d4272004-06-13 20:20:40 +00009493#ifdef FEAT_EVAL
9494 /* set v:cmdarg (only when there is a matching pattern) */
9495 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
9496 if (eap != NULL)
9497 {
9498 save_cmdarg = set_cmdarg(eap, NULL);
9499 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9500 }
9501 else
9502 save_cmdarg = NULL; /* avoid gcc warning */
9503#endif
9504 retval = TRUE;
9505 /* mark the last pattern, to avoid an endless loop when more patterns
9506 * are added when executing autocommands */
9507 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9508 ap->last = FALSE;
9509 ap->last = TRUE;
9510 check_lnums(TRUE); /* make sure cursor and topline are valid */
9511 do_cmdline(NULL, getnextac, (void *)&patcmd,
9512 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9513#ifdef FEAT_EVAL
9514 if (eap != NULL)
9515 {
9516 (void)set_cmdarg(NULL, save_cmdarg);
9517 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9518 }
9519#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009520 /* delete from active_apc_list */
9521 if (active_apc_list == &patcmd) /* just in case */
9522 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009523 }
9524
9525 --RedrawingDisabled;
9526 autocmd_busy = save_autocmd_busy;
9527 filechangeshell_busy = FALSE;
9528 autocmd_nested = save_autocmd_nested;
9529 vim_free(sourcing_name);
9530 sourcing_name = save_sourcing_name;
9531 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009532 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009533 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009534 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009535 autocmd_bufnr = save_autocmd_bufnr;
9536 autocmd_match = save_autocmd_match;
9537#ifdef FEAT_EVAL
9538 current_SID = save_current_SID;
9539 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00009540# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009541 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009542 prof_child_exit(&wait_time);
9543# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009544#endif
9545 vim_free(fname);
9546 vim_free(sfname);
9547 --nesting; /* see matching increment above */
9548
9549 /*
9550 * When stopping to execute autocommands, restore the search patterns and
Bram Moolenaar4c7ab1b2014-04-06 20:45:43 +02009551 * the redo buffer. Free buffers in the au_pending_free_buf list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009552 */
9553 if (!autocmd_busy)
9554 {
9555 restore_search_patterns();
9556 restoreRedobuff();
9557 did_filetype = FALSE;
Bram Moolenaar4c7ab1b2014-04-06 20:45:43 +02009558 while (au_pending_free_buf != NULL)
9559 {
9560 buf_T *b = au_pending_free_buf->b_next;
9561 vim_free(au_pending_free_buf);
9562 au_pending_free_buf = b;
9563 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009564 }
9565
9566 /*
9567 * Some events don't set or reset the Changed flag.
9568 * Check if still in the same buffer!
9569 */
9570 if (curbuf == old_curbuf
9571 && (event == EVENT_BUFREADPOST
9572 || event == EVENT_BUFWRITEPOST
9573 || event == EVENT_FILEAPPENDPOST
9574 || event == EVENT_VIMLEAVE
9575 || event == EVENT_VIMLEAVEPRE))
9576 {
9577#ifdef FEAT_TITLE
9578 if (curbuf->b_changed != save_changed)
9579 need_maketitle = TRUE;
9580#endif
9581 curbuf->b_changed = save_changed;
9582 }
9583
9584 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009585
9586BYPASS_AU:
9587 /* When wiping out a buffer make sure all its buffer-local autocommands
9588 * are deleted. */
9589 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9590 aubuflocal_remove(buf);
9591
Bram Moolenaar071d4272004-06-13 20:20:40 +00009592 return retval;
9593}
9594
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009595# ifdef FEAT_EVAL
9596static char_u *old_termresponse = NULL;
9597# endif
9598
9599/*
9600 * Block triggering autocommands until unblock_autocmd() is called.
9601 * Can be used recursively, so long as it's symmetric.
9602 */
9603 void
9604block_autocmds()
9605{
9606# ifdef FEAT_EVAL
9607 /* Remember the value of v:termresponse. */
9608 if (autocmd_blocked == 0)
9609 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9610# endif
9611 ++autocmd_blocked;
9612}
9613
9614 void
9615unblock_autocmds()
9616{
9617 --autocmd_blocked;
9618
9619# ifdef FEAT_EVAL
9620 /* When v:termresponse was set while autocommands were blocked, trigger
9621 * the autocommands now. Esp. useful when executing a shell command
9622 * during startup (vimdiff). */
9623 if (autocmd_blocked == 0
9624 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9625 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9626# endif
9627}
9628
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009629 int
9630is_autocmd_blocked()
9631{
9632 return autocmd_blocked != 0;
9633}
9634
Bram Moolenaar071d4272004-06-13 20:20:40 +00009635/*
9636 * Find next autocommand pattern that matches.
9637 */
9638 static void
9639auto_next_pat(apc, stop_at_last)
9640 AutoPatCmd *apc;
9641 int stop_at_last; /* stop when 'last' flag is set */
9642{
9643 AutoPat *ap;
9644 AutoCmd *cp;
9645 char_u *name;
9646 char *s;
9647
9648 vim_free(sourcing_name);
9649 sourcing_name = NULL;
9650
9651 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9652 {
9653 apc->curpat = NULL;
9654
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009655 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009656 * the group matches. For buffer-local autocommands only check the
9657 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009658 if (ap->pat != NULL && ap->cmds != NULL
9659 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9660 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009661 /* execution-condition */
9662 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009663 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
9664 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009665 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009666 {
9667 name = event_nr2name(apc->event);
9668 s = _("%s Auto commands for \"%s\"");
9669 sourcing_name = alloc((unsigned)(STRLEN(s)
9670 + STRLEN(name) + ap->patlen + 1));
9671 if (sourcing_name != NULL)
9672 {
9673 sprintf((char *)sourcing_name, s,
9674 (char *)name, (char *)ap->pat);
9675 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009676 {
9677 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009678 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009679 verbose_leave();
9680 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009681 }
9682
9683 apc->curpat = ap;
9684 apc->nextcmd = ap->cmds;
9685 /* mark last command */
9686 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9687 cp->last = FALSE;
9688 cp->last = TRUE;
9689 }
9690 line_breakcheck();
9691 if (apc->curpat != NULL) /* found a match */
9692 break;
9693 }
9694 if (stop_at_last && ap->last)
9695 break;
9696 }
9697}
9698
9699/*
9700 * Get next autocommand command.
9701 * Called by do_cmdline() to get the next line for ":if".
9702 * Returns allocated string, or NULL for end of autocommands.
9703 */
Bram Moolenaar21691f82012-12-05 19:13:18 +01009704 char_u *
Bram Moolenaar071d4272004-06-13 20:20:40 +00009705getnextac(c, cookie, indent)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009706 int c UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009707 void *cookie;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009708 int indent UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009709{
9710 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9711 char_u *retval;
9712 AutoCmd *ac;
9713
9714 /* Can be called again after returning the last line. */
9715 if (acp->curpat == NULL)
9716 return NULL;
9717
9718 /* repeat until we find an autocommand to execute */
9719 for (;;)
9720 {
9721 /* skip removed commands */
9722 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9723 if (acp->nextcmd->last)
9724 acp->nextcmd = NULL;
9725 else
9726 acp->nextcmd = acp->nextcmd->next;
9727
9728 if (acp->nextcmd != NULL)
9729 break;
9730
9731 /* at end of commands, find next pattern that matches */
9732 if (acp->curpat->last)
9733 acp->curpat = NULL;
9734 else
9735 acp->curpat = acp->curpat->next;
9736 if (acp->curpat != NULL)
9737 auto_next_pat(acp, TRUE);
9738 if (acp->curpat == NULL)
9739 return NULL;
9740 }
9741
9742 ac = acp->nextcmd;
9743
9744 if (p_verbose >= 9)
9745 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009746 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009747 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009748 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009749 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009750 }
9751 retval = vim_strsave(ac->cmd);
9752 autocmd_nested = ac->nested;
9753#ifdef FEAT_EVAL
9754 current_SID = ac->scriptID;
9755#endif
9756 if (ac->last)
9757 acp->nextcmd = NULL;
9758 else
9759 acp->nextcmd = ac->next;
9760 return retval;
9761}
9762
9763/*
9764 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009765 * To account for buffer-local autocommands, function needs to know
9766 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009767 */
9768 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009769has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009770 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009771 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009772 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009773{
9774 AutoPat *ap;
9775 char_u *fname;
9776 char_u *tail = gettail(sfname);
9777 int retval = FALSE;
9778
9779 fname = FullName_save(sfname, FALSE);
9780 if (fname == NULL)
9781 return FALSE;
9782
9783#ifdef BACKSLASH_IN_FILENAME
9784 /*
9785 * Replace all backslashes with forward slashes. This makes the
9786 * autocommand patterns portable between Unix and MS-DOS.
9787 */
9788 sfname = vim_strsave(sfname);
9789 if (sfname != NULL)
9790 forward_slash(sfname);
9791 forward_slash(fname);
9792#endif
9793
9794 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9795 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009796 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009797 ? match_file_pat(NULL, ap->reg_prog,
9798 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009799 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009800 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009801 {
9802 retval = TRUE;
9803 break;
9804 }
9805
9806 vim_free(fname);
9807#ifdef BACKSLASH_IN_FILENAME
9808 vim_free(sfname);
9809#endif
9810
9811 return retval;
9812}
9813
9814#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9815/*
9816 * Function given to ExpandGeneric() to obtain the list of autocommand group
9817 * names.
9818 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009819 char_u *
9820get_augroup_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009821 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009822 int idx;
9823{
9824 if (idx == augroups.ga_len) /* add "END" add the end */
9825 return (char_u *)"END";
9826 if (idx >= augroups.ga_len) /* end of list */
9827 return NULL;
9828 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
9829 return (char_u *)"";
9830 return AUGROUP_NAME(idx); /* return a name */
9831}
9832
9833static int include_groups = FALSE;
9834
9835 char_u *
9836set_context_in_autocmd(xp, arg, doautocmd)
9837 expand_T *xp;
9838 char_u *arg;
Bram Moolenaard812df62008-11-09 12:46:09 +00009839 int doautocmd; /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009840{
9841 char_u *p;
9842 int group;
9843
9844 /* check for a group name, skip it if present */
9845 include_groups = FALSE;
9846 p = arg;
9847 group = au_get_grouparg(&arg);
9848 if (group == AUGROUP_ERROR)
9849 return NULL;
9850 /* If there only is a group name that's what we expand. */
9851 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
9852 {
9853 arg = p;
9854 group = AUGROUP_ALL;
9855 }
9856
9857 /* skip over event name */
9858 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
9859 if (*p == ',')
9860 arg = p + 1;
9861 if (*p == NUL)
9862 {
9863 if (group == AUGROUP_ALL)
9864 include_groups = TRUE;
9865 xp->xp_context = EXPAND_EVENTS; /* expand event name */
9866 xp->xp_pattern = arg;
9867 return NULL;
9868 }
9869
9870 /* skip over pattern */
9871 arg = skipwhite(p);
9872 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
9873 arg++;
9874 if (*arg)
9875 return arg; /* expand (next) command */
9876
9877 if (doautocmd)
9878 xp->xp_context = EXPAND_FILES; /* expand file names */
9879 else
9880 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9881 return NULL;
9882}
9883
9884/*
9885 * Function given to ExpandGeneric() to obtain the list of event names.
9886 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009887 char_u *
9888get_event_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009889 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009890 int idx;
9891{
9892 if (idx < augroups.ga_len) /* First list group names, if wanted */
9893 {
9894 if (!include_groups || AUGROUP_NAME(idx) == NULL)
9895 return (char_u *)""; /* skip deleted entries */
9896 return AUGROUP_NAME(idx); /* return a name */
9897 }
9898 return (char_u *)event_names[idx - augroups.ga_len].name;
9899}
9900
9901#endif /* FEAT_CMDL_COMPL */
9902
9903/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009904 * Return TRUE if autocmd is supported.
9905 */
9906 int
9907autocmd_supported(name)
9908 char_u *name;
9909{
9910 char_u *p;
9911
9912 return (event_name2nr(name, &p) != NUM_EVENTS);
9913}
9914
9915/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00009916 * Return TRUE if an autocommand is defined for a group, event and
9917 * pattern: The group can be omitted to accept any group. "event" and "pattern"
9918 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
9919 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
9920 * Used for:
9921 * exists("#Group") or
9922 * exists("#Group#Event") or
9923 * exists("#Group#Event#pat") or
9924 * exists("#Event") or
9925 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00009926 */
9927 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00009928au_exists(arg)
9929 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009930{
Bram Moolenaar195d6352005-12-19 22:08:24 +00009931 char_u *arg_save;
9932 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009933 char_u *event_name;
9934 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00009935 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009936 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009937 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00009938 int group;
9939 int retval = FALSE;
9940
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009941 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009942 arg_save = vim_strsave(arg);
9943 if (arg_save == NULL)
9944 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009945 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00009946 if (p != NULL)
9947 *p++ = NUL;
9948
9949 /* First, look for an autocmd group name */
9950 group = au_find_group(arg_save);
9951 if (group == AUGROUP_ERROR)
9952 {
9953 /* Didn't match a group name, assume the first argument is an event. */
9954 group = AUGROUP_ALL;
9955 event_name = arg_save;
9956 }
9957 else
9958 {
9959 if (p == NULL)
9960 {
9961 /* "Group": group name is present and it's recognized */
9962 retval = TRUE;
9963 goto theend;
9964 }
9965
9966 /* Must be "Group#Event" or "Group#Event#pat". */
9967 event_name = p;
9968 p = vim_strchr(event_name, '#');
9969 if (p != NULL)
9970 *p++ = NUL; /* "Group#Event#pat" */
9971 }
9972
9973 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009974
9975 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009976 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009977
9978 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009979 if (event == NUM_EVENTS)
9980 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009981
9982 /* Find the first autocommand for this event.
9983 * If there isn't any, return FALSE;
9984 * If there is one and no pattern given, return TRUE; */
9985 ap = first_autopat[(int)event];
9986 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009987 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009988
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009989 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9990 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009991 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009992 buflocal_buf = curbuf;
9993
Bram Moolenaar071d4272004-06-13 20:20:40 +00009994 /* Check if there is an autocommand with the given pattern. */
9995 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009996 /* only use a pattern when it has not been removed and has commands. */
9997 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009998 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00009999 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010000 && (pattern == NULL
10001 || (buflocal_buf == NULL
10002 ? fnamecmp(ap->pat, pattern) == 0
10003 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +000010004 {
10005 retval = TRUE;
10006 break;
10007 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010008
Bram Moolenaar195d6352005-12-19 22:08:24 +000010009theend:
10010 vim_free(arg_save);
10011 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010012}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010013
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010014#else /* FEAT_AUTOCMD */
10015
10016/*
10017 * Prepare for executing commands for (hidden) buffer "buf".
10018 * This is the non-autocommand version, it simply saves "curbuf" and sets
10019 * "curbuf" and "curwin" to match "buf".
10020 */
10021 void
10022aucmd_prepbuf(aco, buf)
10023 aco_save_T *aco; /* structure to save values in */
10024 buf_T *buf; /* new curbuf */
10025{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010026 aco->save_curbuf = curbuf;
10027 --curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010028 curbuf = buf;
10029 curwin->w_buffer = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010030 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010031}
10032
10033/*
10034 * Restore after executing commands for a (hidden) buffer.
10035 * This is the non-autocommand version.
10036 */
10037 void
10038aucmd_restbuf(aco)
10039 aco_save_T *aco; /* structure holding saved values */
10040{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010041 --curbuf->b_nwindows;
10042 curbuf = aco->save_curbuf;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010043 curwin->w_buffer = curbuf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010044 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010045}
10046
Bram Moolenaar071d4272004-06-13 20:20:40 +000010047#endif /* FEAT_AUTOCMD */
10048
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010049
Bram Moolenaar071d4272004-06-13 20:20:40 +000010050#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
10051/*
Bram Moolenaar748bf032005-02-02 23:04:36 +000010052 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
10053 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
10054 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010055 * Used for autocommands and 'wildignore'.
10056 * Returns TRUE if there is a match, FALSE otherwise.
10057 */
10058 int
Bram Moolenaar748bf032005-02-02 23:04:36 +000010059match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010060 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +000010061 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010062 char_u *fname; /* full path of file name */
10063 char_u *sfname; /* short file name or NULL */
10064 char_u *tail; /* tail of path */
10065 int allow_dirs; /* allow matching with dir */
10066{
10067 regmatch_T regmatch;
10068 int result = FALSE;
10069#ifdef FEAT_OSFILETYPE
10070 int no_pattern = FALSE; /* TRUE if check is filetype only */
10071 char_u *type_start;
10072 char_u c;
10073 int match = FALSE;
10074#endif
10075
Bram Moolenaar71afbfe2013-03-19 16:49:16 +010010076 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010077#ifdef FEAT_OSFILETYPE
10078 if (*pattern == '<')
10079 {
10080 /* There is a filetype condition specified with this pattern.
10081 * Check the filetype matches first. If not, don't bother with the
10082 * pattern (set regprog to NULL).
10083 * Always use magic for the regexp.
10084 */
10085
10086 for (type_start = pattern + 1; (c = *pattern); pattern++)
10087 {
10088 if ((c == ';' || c == '>') && match == FALSE)
10089 {
10090 *pattern = NUL; /* Terminate the string */
Bram Moolenaar05334432011-07-20 18:29:39 +020010091 /* TODO: match with 'filetype' of buffer that "fname" comes
10092 * from. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010093 match = mch_check_filetype(fname, type_start);
10094 *pattern = c; /* Restore the terminator */
10095 type_start = pattern + 1;
10096 }
10097 if (c == '>')
10098 break;
10099 }
10100
10101 /* (c should never be NUL, but check anyway) */
10102 if (match == FALSE || c == NUL)
10103 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
10104 else if (*pattern == NUL)
10105 {
10106 regmatch.regprog = NULL; /* Vim will try to free regprog later */
10107 no_pattern = TRUE; /* Always matches - don't check pat. */
10108 }
10109 else
10110 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
10111 }
10112 else
10113#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +000010114 {
10115 if (prog != NULL)
10116 regmatch.regprog = prog;
10117 else
10118 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
10119 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010120
10121 /*
10122 * Try for a match with the pattern with:
10123 * 1. the full file name, when the pattern has a '/'.
10124 * 2. the short file name, when the pattern has a '/'.
10125 * 3. the tail of the file name, when the pattern has no '/'.
10126 */
10127 if (
10128#ifdef FEAT_OSFILETYPE
10129 /* If the check is for a filetype only and we don't care
10130 * about the path then skip all the regexp stuff.
10131 */
10132 no_pattern ||
10133#endif
10134 (regmatch.regprog != NULL
10135 && ((allow_dirs
10136 && (vim_regexec(&regmatch, fname, (colnr_T)0)
10137 || (sfname != NULL
10138 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
10139 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
10140 result = TRUE;
10141
Bram Moolenaar748bf032005-02-02 23:04:36 +000010142 if (prog == NULL)
Bram Moolenaar473de612013-06-08 18:19:48 +020010143 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010144 return result;
10145}
10146#endif
10147
10148#if defined(FEAT_WILDIGN) || defined(PROTO)
10149/*
10150 * Return TRUE if a file matches with a pattern in "list".
10151 * "list" is a comma-separated list of patterns, like 'wildignore'.
10152 * "sfname" is the short file name or NULL, "ffname" the long file name.
10153 */
10154 int
10155match_file_list(list, sfname, ffname)
10156 char_u *list;
10157 char_u *sfname;
10158 char_u *ffname;
10159{
10160 char_u buf[100];
10161 char_u *tail;
10162 char_u *regpat;
10163 char allow_dirs;
10164 int match;
10165 char_u *p;
10166
10167 tail = gettail(sfname);
10168
10169 /* try all patterns in 'wildignore' */
10170 p = list;
10171 while (*p)
10172 {
10173 copy_option_part(&p, buf, 100, ",");
10174 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
10175 if (regpat == NULL)
10176 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +000010177 match = match_file_pat(regpat, NULL, ffname, sfname,
10178 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010179 vim_free(regpat);
10180 if (match)
10181 return TRUE;
10182 }
10183 return FALSE;
10184}
10185#endif
10186
10187/*
10188 * Convert the given pattern "pat" which has shell style wildcards in it, into
10189 * a regular expression, and return the result in allocated memory. If there
10190 * is a directory path separator to be matched, then TRUE is put in
10191 * allow_dirs, otherwise FALSE is put there -- webb.
10192 * Handle backslashes before special characters, like "\*" and "\ ".
10193 *
10194 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
10195 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
10196 *
10197 * Returns NULL when out of memory.
10198 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010199 char_u *
10200file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
10201 char_u *pat;
10202 char_u *pat_end; /* first char after pattern or NULL */
10203 char *allow_dirs; /* Result passed back out in here */
Bram Moolenaar78a15312009-05-15 19:33:18 +000010204 int no_bslash UNUSED; /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010205{
10206 int size;
10207 char_u *endp;
10208 char_u *reg_pat;
10209 char_u *p;
10210 int i;
10211 int nested = 0;
10212 int add_dollar = TRUE;
10213#ifdef FEAT_OSFILETYPE
10214 int check_length = 0;
10215#endif
10216
10217 if (allow_dirs != NULL)
10218 *allow_dirs = FALSE;
10219 if (pat_end == NULL)
10220 pat_end = pat + STRLEN(pat);
10221
10222#ifdef FEAT_OSFILETYPE
10223 /* Find out how much of the string is the filetype check */
10224 if (*pat == '<')
10225 {
10226 /* Count chars until the next '>' */
10227 for (p = pat + 1; p < pat_end && *p != '>'; p++)
10228 ;
10229 if (p < pat_end)
10230 {
10231 /* Pattern is of the form <.*>.* */
10232 check_length = p - pat + 1;
10233 if (p + 1 >= pat_end)
10234 {
10235 /* The 'pattern' is a filetype check ONLY */
10236 reg_pat = (char_u *)alloc(check_length + 1);
10237 if (reg_pat != NULL)
10238 {
10239 mch_memmove(reg_pat, pat, (size_t)check_length);
10240 reg_pat[check_length] = NUL;
10241 }
10242 return reg_pat;
10243 }
10244 }
10245 /* else: there was no closing '>' - assume it was a normal pattern */
10246
10247 }
10248 pat += check_length;
10249 size = 2 + check_length;
10250#else
10251 size = 2; /* '^' at start, '$' at end */
10252#endif
10253
10254 for (p = pat; p < pat_end; p++)
10255 {
10256 switch (*p)
10257 {
10258 case '*':
10259 case '.':
10260 case ',':
10261 case '{':
10262 case '}':
10263 case '~':
10264 size += 2; /* extra backslash */
10265 break;
10266#ifdef BACKSLASH_IN_FILENAME
10267 case '\\':
10268 case '/':
10269 size += 4; /* could become "[\/]" */
10270 break;
10271#endif
10272 default:
10273 size++;
10274# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010275 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010276 {
10277 ++p;
10278 ++size;
10279 }
10280# endif
10281 break;
10282 }
10283 }
10284 reg_pat = alloc(size + 1);
10285 if (reg_pat == NULL)
10286 return NULL;
10287
10288#ifdef FEAT_OSFILETYPE
10289 /* Copy the type check in to the start. */
10290 if (check_length)
10291 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
10292 i = check_length;
10293#else
10294 i = 0;
10295#endif
10296
10297 if (pat[0] == '*')
10298 while (pat[0] == '*' && pat < pat_end - 1)
10299 pat++;
10300 else
10301 reg_pat[i++] = '^';
10302 endp = pat_end - 1;
10303 if (*endp == '*')
10304 {
10305 while (endp - pat > 0 && *endp == '*')
10306 endp--;
10307 add_dollar = FALSE;
10308 }
10309 for (p = pat; *p && nested >= 0 && p <= endp; p++)
10310 {
10311 switch (*p)
10312 {
10313 case '*':
10314 reg_pat[i++] = '.';
10315 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +000010316 while (p[1] == '*') /* "**" matches like "*" */
10317 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010318 break;
10319 case '.':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010320 case '~':
10321 reg_pat[i++] = '\\';
10322 reg_pat[i++] = *p;
10323 break;
10324 case '?':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010325 reg_pat[i++] = '.';
10326 break;
10327 case '\\':
10328 if (p[1] == NUL)
10329 break;
10330#ifdef BACKSLASH_IN_FILENAME
10331 if (!no_bslash)
10332 {
10333 /* translate:
10334 * "\x" to "\\x" e.g., "dir\file"
10335 * "\*" to "\\.*" e.g., "dir\*.c"
10336 * "\?" to "\\." e.g., "dir\??.c"
10337 * "\+" to "\+" e.g., "fileX\+.c"
10338 */
10339 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
10340 && p[1] != '+')
10341 {
10342 reg_pat[i++] = '[';
10343 reg_pat[i++] = '\\';
10344 reg_pat[i++] = '/';
10345 reg_pat[i++] = ']';
10346 if (allow_dirs != NULL)
10347 *allow_dirs = TRUE;
10348 break;
10349 }
10350 }
10351#endif
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010352 /* Undo escaping from ExpandEscape():
10353 * foo\?bar -> foo?bar
10354 * foo\%bar -> foo%bar
10355 * foo\,bar -> foo,bar
10356 * foo\ bar -> foo bar
10357 * Don't unescape \, * and others that are also special in a
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010358 * regexp.
10359 * An escaped { must be unescaped since we use magic not
Bram Moolenaara946afe2013-08-02 15:22:39 +020010360 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010361 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010362 if (*++p == '?'
10363#ifdef BACKSLASH_IN_FILENAME
10364 && no_bslash
10365#endif
10366 )
10367 reg_pat[i++] = '?';
10368 else
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010369 if (*p == ',' || *p == '%' || *p == '#'
Bram Moolenaara946afe2013-08-02 15:22:39 +020010370 || *p == ' ' || *p == '{' || *p == '}')
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010371 reg_pat[i++] = *p;
Bram Moolenaara946afe2013-08-02 15:22:39 +020010372 else if (*p == '\\' && p[1] == '\\' && p[2] == '{')
10373 {
10374 reg_pat[i++] = '\\';
10375 reg_pat[i++] = '{';
10376 p += 2;
10377 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010378 else
10379 {
10380 if (allow_dirs != NULL && vim_ispathsep(*p)
10381#ifdef BACKSLASH_IN_FILENAME
10382 && (!no_bslash || *p != '\\')
10383#endif
10384 )
10385 *allow_dirs = TRUE;
10386 reg_pat[i++] = '\\';
10387 reg_pat[i++] = *p;
10388 }
10389 break;
10390#ifdef BACKSLASH_IN_FILENAME
10391 case '/':
10392 reg_pat[i++] = '[';
10393 reg_pat[i++] = '\\';
10394 reg_pat[i++] = '/';
10395 reg_pat[i++] = ']';
10396 if (allow_dirs != NULL)
10397 *allow_dirs = TRUE;
10398 break;
10399#endif
10400 case '{':
10401 reg_pat[i++] = '\\';
10402 reg_pat[i++] = '(';
10403 nested++;
10404 break;
10405 case '}':
10406 reg_pat[i++] = '\\';
10407 reg_pat[i++] = ')';
10408 --nested;
10409 break;
10410 case ',':
10411 if (nested)
10412 {
10413 reg_pat[i++] = '\\';
10414 reg_pat[i++] = '|';
10415 }
10416 else
10417 reg_pat[i++] = ',';
10418 break;
10419 default:
10420# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010421 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010422 reg_pat[i++] = *p++;
10423 else
10424# endif
10425 if (allow_dirs != NULL && vim_ispathsep(*p))
10426 *allow_dirs = TRUE;
10427 reg_pat[i++] = *p;
10428 break;
10429 }
10430 }
10431 if (add_dollar)
10432 reg_pat[i++] = '$';
10433 reg_pat[i] = NUL;
10434 if (nested != 0)
10435 {
10436 if (nested < 0)
10437 EMSG(_("E219: Missing {."));
10438 else
10439 EMSG(_("E220: Missing }."));
10440 vim_free(reg_pat);
10441 reg_pat = NULL;
10442 }
10443 return reg_pat;
10444}
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010445
10446#if defined(EINTR) || defined(PROTO)
10447/*
10448 * Version of read() that retries when interrupted by EINTR (possibly
10449 * by a SIGWINCH).
10450 */
10451 long
10452read_eintr(fd, buf, bufsize)
10453 int fd;
10454 void *buf;
10455 size_t bufsize;
10456{
10457 long ret;
10458
10459 for (;;)
10460 {
10461 ret = vim_read(fd, buf, bufsize);
10462 if (ret >= 0 || errno != EINTR)
10463 break;
10464 }
10465 return ret;
10466}
10467
10468/*
10469 * Version of write() that retries when interrupted by EINTR (possibly
10470 * by a SIGWINCH).
10471 */
10472 long
10473write_eintr(fd, buf, bufsize)
10474 int fd;
10475 void *buf;
10476 size_t bufsize;
10477{
10478 long ret = 0;
10479 long wlen;
10480
10481 /* Repeat the write() so long it didn't fail, other than being interrupted
10482 * by a signal. */
10483 while (ret < (long)bufsize)
10484 {
Bram Moolenaar9c263032010-12-17 18:06:06 +010010485 wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010486 if (wlen < 0)
10487 {
10488 if (errno != EINTR)
10489 break;
10490 }
10491 else
10492 ret += wlen;
10493 }
10494 return ret;
10495}
10496#endif