blob: 38dc2597da66b47db0abbb9f21caafd68670abb1 [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)
Bram Moolenaara7611f62014-05-02 15:46:14 +02006900 || st.st_size != buf->b_orig_size
Bram Moolenaar071d4272004-06-13 20:20:40 +00006901#ifdef HAVE_ST_MODE
6902 || (int)st.st_mode != buf->b_orig_mode
6903#else
6904 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6905#endif
6906 ))
6907 {
6908 retval = 1;
6909
Bram Moolenaar316059c2006-01-14 21:18:42 +00006910 /* set b_mtime to stop further warnings (e.g., when executing
6911 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006912 if (stat_res < 0)
6913 {
6914 buf->b_mtime = 0;
6915 buf->b_orig_size = 0;
6916 buf->b_orig_mode = 0;
6917 }
6918 else
6919 buf_store_time(buf, &st, buf->b_ffname);
6920
6921 /* Don't do anything for a directory. Might contain the file
6922 * explorer. */
6923 if (mch_isdir(buf->b_fname))
6924 ;
6925
6926 /*
6927 * If 'autoread' is set, the buffer has no changes and the file still
6928 * exists, reload the buffer. Use the buffer-local option value if it
6929 * was set, the global option value otherwise.
6930 */
6931 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6932 && !bufIsChanged(buf) && stat_res >= 0)
6933 reload = TRUE;
6934 else
6935 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006936 if (stat_res < 0)
6937 reason = "deleted";
6938 else if (bufIsChanged(buf))
6939 reason = "conflict";
6940 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6941 reason = "changed";
6942 else if (orig_mode != buf->b_orig_mode)
6943 reason = "mode";
6944 else
6945 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006946
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006947#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006948 /*
6949 * Only give the warning if there are no FileChangedShell
6950 * autocommands.
6951 * Avoid being called recursively by setting "busy".
6952 */
6953 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006954# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006955 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6956 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006957# endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006958 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006959 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6960 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006961 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006962 busy = FALSE;
6963 if (n)
6964 {
6965 if (!buf_valid(buf))
6966 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006967# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006968 s = get_vim_var_str(VV_FCS_CHOICE);
6969 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6970 reload = TRUE;
6971 else if (STRCMP(s, "ask") == 0)
6972 n = FALSE;
6973 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006974# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006975 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006976 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006977 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006978#endif
6979 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006980 if (*reason == 'd')
6981 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006982 else
6983 {
6984 helpmesg = TRUE;
6985#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6986 can_reload = TRUE;
6987#endif
6988 /*
6989 * Check if the file contents really changed to avoid
6990 * giving a warning when only the timestamp was set (e.g.,
6991 * checked out of CVS). Always warn when the buffer was
6992 * changed.
6993 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006994 if (reason[2] == 'n')
6995 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006996 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006997 mesg2 = _("See \":help W12\" for more info.");
6998 }
6999 else if (reason[1] == 'h')
7000 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007001 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007002 mesg2 = _("See \":help W11\" for more info.");
7003 }
7004 else if (*reason == 'm')
7005 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007006 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007007 mesg2 = _("See \":help W16\" for more info.");
7008 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00007009 else
7010 /* Only timestamp changed, store it to avoid a warning
7011 * in check_mtime() later. */
7012 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007013 }
7014 }
7015 }
7016
7017 }
7018 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
7019 && vim_fexists(buf->b_ffname))
7020 {
7021 retval = 1;
7022 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
7023 buf->b_flags |= BF_NEW_W;
7024#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7025 can_reload = TRUE;
7026#endif
7027 }
7028
7029 if (mesg != NULL)
7030 {
7031 path = home_replace_save(buf, buf->b_fname);
7032 if (path != NULL)
7033 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007034 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007035 mesg2 = "";
7036 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
7037 + STRLEN(mesg2) + 2));
7038 sprintf((char *)tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00007039#ifdef FEAT_EVAL
7040 /* Set warningmsg here, before the unimportant and output-specific
7041 * mesg2 has been appended. */
7042 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
7043#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007044#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7045 if (can_reload)
7046 {
7047 if (*mesg2 != NUL)
7048 {
7049 STRCAT(tbuf, "\n");
7050 STRCAT(tbuf, mesg2);
7051 }
7052 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01007053 (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007054 reload = TRUE;
7055 }
7056 else
7057#endif
7058 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
7059 {
7060 if (*mesg2 != NUL)
7061 {
7062 STRCAT(tbuf, "; ");
7063 STRCAT(tbuf, mesg2);
7064 }
7065 EMSG(tbuf);
7066 retval = 2;
7067 }
7068 else
7069 {
Bram Moolenaared203462004-06-16 11:19:22 +00007070# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00007071 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00007072# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007073 {
7074 msg_start();
7075 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
7076 if (*mesg2 != NUL)
7077 msg_puts_attr((char_u *)mesg2,
7078 hl_attr(HLF_W) + MSG_HIST);
7079 msg_clr_eos();
7080 (void)msg_end();
7081 if (emsg_silent == 0)
7082 {
7083 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00007084# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00007085 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00007086# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007087 /* give the user some time to think about it */
7088 ui_delay(1000L, TRUE);
7089
7090 /* don't redraw and erase the message */
7091 redraw_cmdline = FALSE;
7092 }
7093 }
7094 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007095 }
7096
7097 vim_free(path);
7098 vim_free(tbuf);
7099 }
7100 }
7101
7102 if (reload)
Bram Moolenaar465748e2012-08-29 18:50:54 +02007103 {
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007104 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00007105 buf_reload(buf, orig_mode);
Bram Moolenaar465748e2012-08-29 18:50:54 +02007106#ifdef FEAT_PERSISTENT_UNDO
7107 if (buf->b_p_udf && buf->b_ffname != NULL)
7108 {
7109 char_u hash[UNDO_HASH_SIZE];
7110 buf_T *save_curbuf = curbuf;
7111
7112 /* Any existing undo file is unusable, write it now. */
7113 curbuf = buf;
7114 u_compute_hash(hash);
7115 u_write_undo(NULL, FALSE, buf, hash);
7116 curbuf = save_curbuf;
7117 }
7118#endif
7119 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007120
Bram Moolenaar56718732006-03-15 22:53:57 +00007121#ifdef FEAT_AUTOCMD
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00007122 /* Trigger FileChangedShell when the file was changed in any way. */
7123 if (buf_valid(buf) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00007124 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
7125 buf->b_fname, buf->b_fname, FALSE, buf);
7126#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007127#ifdef FEAT_GUI
7128 /* restore this in case an autocommand has set it; it would break
7129 * 'mousefocus' */
7130 need_mouse_correct = save_mouse_correct;
7131#endif
7132
7133 return retval;
7134}
7135
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007136/*
7137 * Reload a buffer that is already loaded.
7138 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00007139 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
7140 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007141 */
7142 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00007143buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007144 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00007145 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007146{
7147 exarg_T ea;
7148 pos_T old_cursor;
7149 linenr_T old_topline;
7150 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007151 buf_T *savebuf;
7152 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007153 aco_save_T aco;
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007154 int flags = READ_NEW;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007155
7156 /* set curwin/curbuf for "buf" and save some things */
7157 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007158
7159 /* We only want to read the text from the file, not reset the syntax
7160 * highlighting, clear marks, diff status, etc. Force the fileformat
7161 * and encoding to be the same. */
7162 if (prep_exarg(&ea, buf) == OK)
7163 {
7164 old_cursor = curwin->w_cursor;
7165 old_topline = curwin->w_topline;
7166
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007167 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007168 {
7169 /* Save all the text, so that the reload can be undone.
7170 * Sync first so that this is a separate undo-able action. */
7171 u_sync(FALSE);
7172 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
7173 flags |= READ_KEEP_UNDO;
7174 }
7175
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007176 /*
7177 * To behave like when a new file is edited (matters for
7178 * BufReadPost autocommands) we first need to delete the current
7179 * buffer contents. But if reading the file fails we should keep
7180 * the old contents. Can't use memory only, the file might be
7181 * too big. Use a hidden buffer to move the buffer contents to.
7182 */
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007183 if (bufempty() || saved == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007184 savebuf = NULL;
7185 else
7186 {
7187 /* Allocate a buffer without putting it in the buffer list. */
7188 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007189 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007190 {
7191 /* Open the memline. */
7192 curbuf = savebuf;
7193 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00007194 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007195 curbuf = buf;
7196 curwin->w_buffer = buf;
7197 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00007198 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007199 || move_lines(buf, savebuf) == FAIL)
7200 {
7201 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
7202 buf->b_fname);
7203 saved = FAIL;
7204 }
7205 }
7206
7207 if (saved == OK)
7208 {
7209 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
7210#ifdef FEAT_AUTOCMD
7211 keep_filetype = TRUE; /* don't detect 'filetype' */
7212#endif
7213 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
7214 (linenr_T)0,
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007215 (linenr_T)MAXLNUM, &ea, flags) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007216 {
7217#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
7218 if (!aborting())
7219#endif
7220 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007221 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007222 {
7223 /* Put the text back from the save buffer. First
7224 * delete any lines that readfile() added. */
7225 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00007226 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007227 break;
7228 (void)move_lines(savebuf, buf);
7229 }
7230 }
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007231 else if (buf == curbuf) /* "buf" still valid */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007232 {
7233 /* Mark the buffer as unmodified and free undo info. */
7234 unchanged(buf, TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007235 if ((flags & READ_KEEP_UNDO) == 0)
7236 {
7237 u_blockfree(buf);
7238 u_clearall(buf);
7239 }
7240 else
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007241 {
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007242 /* Mark all undo states as changed. */
7243 u_unchanged(curbuf);
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007244 }
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007245 }
7246 }
7247 vim_free(ea.cmd);
7248
Bram Moolenaar8424a622006-04-19 21:23:36 +00007249 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007250 wipe_buffer(savebuf, FALSE);
7251
7252#ifdef FEAT_DIFF
7253 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00007254 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007255#endif
7256
7257 /* Restore the topline and cursor position and check it (lines may
7258 * have been removed). */
7259 if (old_topline > curbuf->b_ml.ml_line_count)
7260 curwin->w_topline = curbuf->b_ml.ml_line_count;
7261 else
7262 curwin->w_topline = old_topline;
7263 curwin->w_cursor = old_cursor;
7264 check_cursor();
7265 update_topline();
7266#ifdef FEAT_AUTOCMD
7267 keep_filetype = FALSE;
7268#endif
7269#ifdef FEAT_FOLDING
7270 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007271 win_T *wp;
7272 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007273
7274 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007275 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007276 if (wp->w_buffer == curwin->w_buffer
7277 && !foldmethodIsManual(wp))
7278 foldUpdateAll(wp);
7279 }
7280#endif
7281 /* If the mode didn't change and 'readonly' was set, keep the old
7282 * value; the user probably used the ":view" command. But don't
7283 * reset it, might have had a read error. */
7284 if (orig_mode == curbuf->b_orig_mode)
7285 curbuf->b_p_ro |= old_ro;
Bram Moolenaar52f85b72013-01-30 14:13:56 +01007286
7287 /* Modelines must override settings done by autocommands. */
7288 do_modelines(0);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007289 }
7290
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007291 /* restore curwin/curbuf and a few other things */
7292 aucmd_restbuf(&aco);
7293 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007294}
7295
Bram Moolenaar071d4272004-06-13 20:20:40 +00007296 void
7297buf_store_time(buf, st, fname)
7298 buf_T *buf;
7299 struct stat *st;
Bram Moolenaar78a15312009-05-15 19:33:18 +00007300 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007301{
7302 buf->b_mtime = (long)st->st_mtime;
Bram Moolenaar914703b2010-05-31 21:59:46 +02007303 buf->b_orig_size = st->st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007304#ifdef HAVE_ST_MODE
7305 buf->b_orig_mode = (int)st->st_mode;
7306#else
7307 buf->b_orig_mode = mch_getperm(fname);
7308#endif
7309}
7310
7311/*
7312 * Adjust the line with missing eol, used for the next write.
7313 * Used for do_filter(), when the input lines for the filter are deleted.
7314 */
7315 void
7316write_lnum_adjust(offset)
7317 linenr_T offset;
7318{
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01007319 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
7320 curbuf->b_no_eol_lnum += offset;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007321}
7322
7323#if defined(TEMPDIRNAMES) || defined(PROTO)
7324static long temp_count = 0; /* Temp filename counter. */
7325
7326/*
7327 * Delete the temp directory and all files it contains.
7328 */
7329 void
7330vim_deltempdir()
7331{
7332 char_u **files;
7333 int file_count;
7334 int i;
7335
7336 if (vim_tempdir != NULL)
7337 {
7338 sprintf((char *)NameBuff, "%s*", vim_tempdir);
7339 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
7340 EW_DIR|EW_FILE|EW_SILENT) == OK)
7341 {
7342 for (i = 0; i < file_count; ++i)
7343 mch_remove(files[i]);
7344 FreeWild(file_count, files);
7345 }
7346 gettail(NameBuff)[-1] = NUL;
7347 (void)mch_rmdir(NameBuff);
7348
7349 vim_free(vim_tempdir);
7350 vim_tempdir = NULL;
7351 }
7352}
7353#endif
7354
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007355#ifdef TEMPDIRNAMES
Bram Moolenaar071d4272004-06-13 20:20:40 +00007356/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007357 * Directory "tempdir" was created. Expand this name to a full path and put
7358 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7359 * "tempdir" must be no longer than MAXPATHL.
7360 */
7361 static void
7362vim_settempdir(tempdir)
7363 char_u *tempdir;
7364{
7365 char_u *buf;
7366
7367 buf = alloc((unsigned)MAXPATHL + 2);
7368 if (buf != NULL)
7369 {
7370 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7371 STRCPY(buf, tempdir);
7372# ifdef __EMX__
7373 if (vim_strchr(buf, '/') != NULL)
7374 STRCAT(buf, "/");
7375 else
7376# endif
7377 add_pathsep(buf);
7378 vim_tempdir = vim_strsave(buf);
7379 vim_free(buf);
7380 }
7381}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007382#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007383
7384/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007385 * vim_tempname(): Return a unique name that can be used for a temp file.
7386 *
7387 * The temp file is NOT created.
7388 *
7389 * The returned pointer is to allocated memory.
7390 * The returned pointer is NULL if no valid name was found.
7391 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007392 char_u *
7393vim_tempname(extra_char)
Bram Moolenaar78a15312009-05-15 19:33:18 +00007394 int extra_char UNUSED; /* char to use in the name instead of '?' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007395{
7396#ifdef USE_TMPNAM
7397 char_u itmp[L_tmpnam]; /* use tmpnam() */
7398#else
7399 char_u itmp[TEMPNAMELEN];
7400#endif
7401
7402#ifdef TEMPDIRNAMES
7403 static char *(tempdirs[]) = {TEMPDIRNAMES};
7404 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007405# ifndef EEXIST
7406 struct stat st;
7407# endif
7408
7409 /*
7410 * This will create a directory for private use by this instance of Vim.
7411 * This is done once, and the same directory is used for all temp files.
7412 * This method avoids security problems because of symlink attacks et al.
7413 * It's also a bit faster, because we only need to check for an existing
7414 * file when creating the directory and not for each temp file.
7415 */
7416 if (vim_tempdir == NULL)
7417 {
7418 /*
7419 * Try the entries in TEMPDIRNAMES to create the temp directory.
7420 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007421 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007422 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007423# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007424 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007425 long nr;
7426 long off;
7427# endif
7428
Bram Moolenaar071d4272004-06-13 20:20:40 +00007429 /* expand $TMP, leave room for "/v1100000/999999999" */
7430 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
7431 if (mch_isdir(itmp)) /* directory exists */
7432 {
7433# ifdef __EMX__
7434 /* If $TMP contains a forward slash (perhaps using bash or
7435 * tcsh), don't add a backslash, use a forward slash!
7436 * Adding 2 backslashes didn't work. */
7437 if (vim_strchr(itmp, '/') != NULL)
7438 STRCAT(itmp, "/");
7439 else
7440# endif
7441 add_pathsep(itmp);
7442
Bram Moolenaareaf03392009-11-17 11:08:52 +00007443# ifdef HAVE_MKDTEMP
7444 /* Leave room for filename */
7445 STRCAT(itmp, "vXXXXXX");
7446 if (mkdtemp((char *)itmp) != NULL)
7447 vim_settempdir(itmp);
7448# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007449 /* Get an arbitrary number of up to 6 digits. When it's
7450 * unlikely that it already exists it will be faster,
7451 * otherwise it doesn't matter. The use of mkdir() avoids any
7452 * security problems because of the predictable number. */
7453 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007454 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007455
7456 /* Try up to 10000 different values until we find a name that
7457 * doesn't exist. */
7458 for (off = 0; off < 10000L; ++off)
7459 {
7460 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007461# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007462 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007463# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007464
Bram Moolenaareaf03392009-11-17 11:08:52 +00007465 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7466# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007467 /* If mkdir() does not set errno to EEXIST, check for
7468 * existing file here. There is a race condition then,
7469 * although it's fail-safe. */
7470 if (mch_stat((char *)itmp, &st) >= 0)
7471 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007472# endif
7473# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007474 /* Make sure the umask doesn't remove the executable bit.
7475 * "repl" has been reported to use "177". */
7476 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007477# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007479# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007480 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007481# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007482 if (r == 0)
7483 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007484 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007485 break;
7486 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007487# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007488 /* If the mkdir() didn't fail because the file/dir exists,
7489 * we probably can't create any dir here, try another
7490 * place. */
7491 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007492# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007493 break;
7494 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007495# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007496 if (vim_tempdir != NULL)
7497 break;
7498 }
7499 }
7500 }
7501
7502 if (vim_tempdir != NULL)
7503 {
7504 /* There is no need to check if the file exists, because we own the
7505 * directory and nobody else creates a file in it. */
7506 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7507 return vim_strsave(itmp);
7508 }
7509
7510 return NULL;
7511
7512#else /* TEMPDIRNAMES */
7513
7514# ifdef WIN3264
7515 char szTempFile[_MAX_PATH + 1];
7516 char buf4[4];
7517 char_u *retval;
7518 char_u *p;
7519
7520 STRCPY(itmp, "");
7521 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
Bram Moolenaarb1891912011-02-09 14:47:03 +01007522 {
7523 szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */
7524 szTempFile[1] = NUL;
7525 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007526 strcpy(buf4, "VIM");
7527 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
7528 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
7529 return NULL;
7530 /* GetTempFileName() will create the file, we don't want that */
7531 (void)DeleteFile(itmp);
7532
7533 /* Backslashes in a temp file name cause problems when filtering with
7534 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7535 * didn't set 'shellslash'. */
7536 retval = vim_strsave(itmp);
7537 if (*p_shcf == '-' || p_ssl)
7538 for (p = retval; *p; ++p)
7539 if (*p == '\\')
7540 *p = '/';
7541 return retval;
7542
7543# else /* WIN3264 */
7544
7545# ifdef USE_TMPNAM
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007546 char_u *p;
7547
Bram Moolenaar071d4272004-06-13 20:20:40 +00007548 /* tmpnam() will make its own name */
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007549 p = tmpnam((char *)itmp);
7550 if (p == NULL || *p == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007551 return NULL;
7552# else
7553 char_u *p;
7554
7555# ifdef VMS_TEMPNAM
7556 /* mktemp() is not working on VMS. It seems to be
7557 * a do-nothing function. Therefore we use tempnam().
7558 */
7559 sprintf((char *)itmp, "VIM%c", extra_char);
7560 p = (char_u *)tempnam("tmp:", (char *)itmp);
7561 if (p != NULL)
7562 {
Bram Moolenaar206f0112014-03-12 16:51:55 +01007563 /* VMS will use '.LIS' if we don't explicitly specify an extension,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007564 * and VIM will then be unable to find the file later */
7565 STRCPY(itmp, p);
7566 STRCAT(itmp, ".txt");
7567 free(p);
7568 }
7569 else
7570 return NULL;
7571# else
7572 STRCPY(itmp, TEMPNAME);
7573 if ((p = vim_strchr(itmp, '?')) != NULL)
7574 *p = extra_char;
7575 if (mktemp((char *)itmp) == NULL)
7576 return NULL;
7577# endif
7578# endif
7579
7580 return vim_strsave(itmp);
7581# endif /* WIN3264 */
7582#endif /* TEMPDIRNAMES */
7583}
7584
7585#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7586/*
7587 * Convert all backslashes in fname to forward slashes in-place.
7588 */
7589 void
7590forward_slash(fname)
7591 char_u *fname;
7592{
7593 char_u *p;
7594
7595 for (p = fname; *p != NUL; ++p)
7596# ifdef FEAT_MBYTE
7597 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007598 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007599 ++p;
7600 else
7601# endif
7602 if (*p == '\\')
7603 *p = '/';
7604}
7605#endif
7606
7607
7608/*
7609 * Code for automatic commands.
7610 *
7611 * Only included when "FEAT_AUTOCMD" has been defined.
7612 */
7613
7614#if defined(FEAT_AUTOCMD) || defined(PROTO)
7615
7616/*
7617 * The autocommands are stored in a list for each event.
7618 * Autocommands for the same pattern, that are consecutive, are joined
7619 * together, to avoid having to match the pattern too often.
7620 * The result is an array of Autopat lists, which point to AutoCmd lists:
7621 *
7622 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7623 * Autopat.cmds Autopat.cmds
7624 * | |
7625 * V V
7626 * AutoCmd.next AutoCmd.next
7627 * | |
7628 * V V
7629 * AutoCmd.next NULL
7630 * |
7631 * V
7632 * NULL
7633 *
7634 * first_autopat[1] --> Autopat.next --> NULL
7635 * Autopat.cmds
7636 * |
7637 * V
7638 * AutoCmd.next
7639 * |
7640 * V
7641 * NULL
7642 * etc.
7643 *
7644 * The order of AutoCmds is important, this is the order in which they were
7645 * defined and will have to be executed.
7646 */
7647typedef struct AutoCmd
7648{
7649 char_u *cmd; /* The command to be executed (NULL
7650 when command has been removed) */
7651 char nested; /* If autocommands nest here */
7652 char last; /* last command in list */
7653#ifdef FEAT_EVAL
7654 scid_T scriptID; /* script ID where defined */
7655#endif
7656 struct AutoCmd *next; /* Next AutoCmd in list */
7657} AutoCmd;
7658
7659typedef struct AutoPat
7660{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007661 char_u *pat; /* pattern as typed (NULL when pattern
7662 has been removed) */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007663 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007664 AutoCmd *cmds; /* list of commands to do */
7665 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007666 int group; /* group ID */
7667 int patlen; /* strlen() of pat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007668 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007669 char allow_dirs; /* Pattern may match whole path */
7670 char last; /* last pattern for apply_autocmds() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007671} AutoPat;
7672
7673static struct event_name
7674{
7675 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007676 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007677} event_names[] =
7678{
7679 {"BufAdd", EVENT_BUFADD},
7680 {"BufCreate", EVENT_BUFADD},
7681 {"BufDelete", EVENT_BUFDELETE},
7682 {"BufEnter", EVENT_BUFENTER},
7683 {"BufFilePost", EVENT_BUFFILEPOST},
7684 {"BufFilePre", EVENT_BUFFILEPRE},
7685 {"BufHidden", EVENT_BUFHIDDEN},
7686 {"BufLeave", EVENT_BUFLEAVE},
7687 {"BufNew", EVENT_BUFNEW},
7688 {"BufNewFile", EVENT_BUFNEWFILE},
7689 {"BufRead", EVENT_BUFREADPOST},
7690 {"BufReadCmd", EVENT_BUFREADCMD},
7691 {"BufReadPost", EVENT_BUFREADPOST},
7692 {"BufReadPre", EVENT_BUFREADPRE},
7693 {"BufUnload", EVENT_BUFUNLOAD},
7694 {"BufWinEnter", EVENT_BUFWINENTER},
7695 {"BufWinLeave", EVENT_BUFWINLEAVE},
7696 {"BufWipeout", EVENT_BUFWIPEOUT},
7697 {"BufWrite", EVENT_BUFWRITEPRE},
7698 {"BufWritePost", EVENT_BUFWRITEPOST},
7699 {"BufWritePre", EVENT_BUFWRITEPRE},
7700 {"BufWriteCmd", EVENT_BUFWRITECMD},
7701 {"CmdwinEnter", EVENT_CMDWINENTER},
7702 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007703 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaarcfa3cae2012-07-10 17:14:56 +02007704 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007705 {"CursorHold", EVENT_CURSORHOLD},
7706 {"CursorHoldI", EVENT_CURSORHOLDI},
7707 {"CursorMoved", EVENT_CURSORMOVED},
7708 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007709 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7710 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007711 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7712 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7713 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7714 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007715 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007716 {"FileChangedRO", EVENT_FILECHANGEDRO},
7717 {"FileReadPost", EVENT_FILEREADPOST},
7718 {"FileReadPre", EVENT_FILEREADPRE},
7719 {"FileReadCmd", EVENT_FILEREADCMD},
7720 {"FileType", EVENT_FILETYPE},
7721 {"FileWritePost", EVENT_FILEWRITEPOST},
7722 {"FileWritePre", EVENT_FILEWRITEPRE},
7723 {"FileWriteCmd", EVENT_FILEWRITECMD},
7724 {"FilterReadPost", EVENT_FILTERREADPOST},
7725 {"FilterReadPre", EVENT_FILTERREADPRE},
7726 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7727 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7728 {"FocusGained", EVENT_FOCUSGAINED},
7729 {"FocusLost", EVENT_FOCUSLOST},
7730 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7731 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007732 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007733 {"InsertChange", EVENT_INSERTCHANGE},
7734 {"InsertEnter", EVENT_INSERTENTER},
7735 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaare659c952011-05-19 17:25:41 +02007736 {"InsertCharPre", EVENT_INSERTCHARPRE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007737 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007738 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7739 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar3b53dfb2012-06-06 18:03:07 +02007740 {"QuitPre", EVENT_QUITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007741 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007742 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007743 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7744 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007745 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007746 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007747 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007748 {"StdinReadPost", EVENT_STDINREADPOST},
7749 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007750 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007751 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007752 {"TabEnter", EVENT_TABENTER},
7753 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007754 {"TermChanged", EVENT_TERMCHANGED},
7755 {"TermResponse", EVENT_TERMRESPONSE},
Bram Moolenaar186628f2013-03-19 13:33:23 +01007756 {"TextChanged", EVENT_TEXTCHANGED},
7757 {"TextChangedI", EVENT_TEXTCHANGEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007758 {"User", EVENT_USER},
7759 {"VimEnter", EVENT_VIMENTER},
7760 {"VimLeave", EVENT_VIMLEAVE},
7761 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7762 {"WinEnter", EVENT_WINENTER},
7763 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007764 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007765 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007766};
7767
7768static AutoPat *first_autopat[NUM_EVENTS] =
7769{
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,
7773 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007774 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7775 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007776};
7777
7778/*
7779 * struct used to keep status while executing autocommands for an event.
7780 */
7781typedef struct AutoPatCmd
7782{
7783 AutoPat *curpat; /* next AutoPat to examine */
7784 AutoCmd *nextcmd; /* next AutoCmd to execute */
7785 int group; /* group being used */
7786 char_u *fname; /* fname to match with */
7787 char_u *sfname; /* sfname to match with */
7788 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007789 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007790 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7791 buf is deleted */
7792 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007793} AutoPatCmd;
7794
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007795static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007796
Bram Moolenaar071d4272004-06-13 20:20:40 +00007797/*
7798 * augroups stores a list of autocmd group names.
7799 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007800static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007801#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7802
7803/*
7804 * The ID of the current group. Group 0 is the default one.
7805 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007806static int current_augroup = AUGROUP_DEFAULT;
7807
7808static int au_need_clean = FALSE; /* need to delete marked patterns */
7809
Bram Moolenaar754b5602006-02-09 23:53:20 +00007810static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007811static void au_remove_pat __ARGS((AutoPat *ap));
7812static void au_remove_cmds __ARGS((AutoPat *ap));
7813static void au_cleanup __ARGS((void));
7814static int au_new_group __ARGS((char_u *name));
7815static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007816static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7817static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007818static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007819static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007820static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007821static 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 +00007822static 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 +00007823static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7824
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007825
Bram Moolenaar754b5602006-02-09 23:53:20 +00007826static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007827static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007828static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007829
7830/*
7831 * Show the autocommands for one AutoPat.
7832 */
7833 static void
7834show_autocmd(ap, event)
7835 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007836 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007837{
7838 AutoCmd *ac;
7839
7840 /* Check for "got_int" (here and at various places below), which is set
7841 * when "q" has been hit for the "--more--" prompt */
7842 if (got_int)
7843 return;
7844 if (ap->pat == NULL) /* pattern has been removed */
7845 return;
7846
7847 msg_putchar('\n');
7848 if (got_int)
7849 return;
7850 if (event != last_event || ap->group != last_group)
7851 {
7852 if (ap->group != AUGROUP_DEFAULT)
7853 {
7854 if (AUGROUP_NAME(ap->group) == NULL)
7855 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7856 else
7857 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7858 msg_puts((char_u *)" ");
7859 }
7860 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7861 last_event = event;
7862 last_group = ap->group;
7863 msg_putchar('\n');
7864 if (got_int)
7865 return;
7866 }
7867 msg_col = 4;
7868 msg_outtrans(ap->pat);
7869
7870 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7871 {
7872 if (ac->cmd != NULL) /* skip removed commands */
7873 {
7874 if (msg_col >= 14)
7875 msg_putchar('\n');
7876 msg_col = 14;
7877 if (got_int)
7878 return;
7879 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007880#ifdef FEAT_EVAL
7881 if (p_verbose > 0)
7882 last_set_msg(ac->scriptID);
7883#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007884 if (got_int)
7885 return;
7886 if (ac->next != NULL)
7887 {
7888 msg_putchar('\n');
7889 if (got_int)
7890 return;
7891 }
7892 }
7893 }
7894}
7895
7896/*
7897 * Mark an autocommand pattern for deletion.
7898 */
7899 static void
7900au_remove_pat(ap)
7901 AutoPat *ap;
7902{
7903 vim_free(ap->pat);
7904 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007905 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007906 au_need_clean = TRUE;
7907}
7908
7909/*
7910 * Mark all commands for a pattern for deletion.
7911 */
7912 static void
7913au_remove_cmds(ap)
7914 AutoPat *ap;
7915{
7916 AutoCmd *ac;
7917
7918 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7919 {
7920 vim_free(ac->cmd);
7921 ac->cmd = NULL;
7922 }
7923 au_need_clean = TRUE;
7924}
7925
7926/*
7927 * Cleanup autocommands and patterns that have been deleted.
7928 * This is only done when not executing autocommands.
7929 */
7930 static void
7931au_cleanup()
7932{
7933 AutoPat *ap, **prev_ap;
7934 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007935 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007936
7937 if (autocmd_busy || !au_need_clean)
7938 return;
7939
7940 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007941 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7942 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007943 {
7944 /* loop over all autocommand patterns */
7945 prev_ap = &(first_autopat[(int)event]);
7946 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7947 {
7948 /* loop over all commands for this pattern */
7949 prev_ac = &(ap->cmds);
7950 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7951 {
7952 /* remove the command if the pattern is to be deleted or when
7953 * the command has been marked for deletion */
7954 if (ap->pat == NULL || ac->cmd == NULL)
7955 {
7956 *prev_ac = ac->next;
7957 vim_free(ac->cmd);
7958 vim_free(ac);
7959 }
7960 else
7961 prev_ac = &(ac->next);
7962 }
7963
7964 /* remove the pattern if it has been marked for deletion */
7965 if (ap->pat == NULL)
7966 {
7967 *prev_ap = ap->next;
Bram Moolenaar473de612013-06-08 18:19:48 +02007968 vim_regfree(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007969 vim_free(ap);
7970 }
7971 else
7972 prev_ap = &(ap->next);
7973 }
7974 }
7975
7976 au_need_clean = FALSE;
7977}
7978
7979/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007980 * Called when buffer is freed, to remove/invalidate related buffer-local
7981 * autocmds.
7982 */
7983 void
7984aubuflocal_remove(buf)
7985 buf_T *buf;
7986{
7987 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007988 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007989 AutoPatCmd *apc;
7990
7991 /* invalidate currently executing autocommands */
7992 for (apc = active_apc_list; apc; apc = apc->next)
7993 if (buf->b_fnum == apc->arg_bufnr)
7994 apc->arg_bufnr = 0;
7995
7996 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007997 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7998 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007999 /* loop over all autocommand patterns */
8000 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8001 if (ap->buflocal_nr == buf->b_fnum)
8002 {
8003 au_remove_pat(ap);
8004 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008005 {
8006 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008007 smsg((char_u *)
8008 _("auto-removing autocommand: %s <buffer=%d>"),
8009 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008010 verbose_leave();
8011 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008012 }
8013 au_cleanup();
8014}
8015
8016/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008017 * Add an autocmd group name.
8018 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8019 */
8020 static int
8021au_new_group(name)
8022 char_u *name;
8023{
8024 int i;
8025
8026 i = au_find_group(name);
8027 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
8028 {
8029 /* First try using a free entry. */
8030 for (i = 0; i < augroups.ga_len; ++i)
8031 if (AUGROUP_NAME(i) == NULL)
8032 break;
8033 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
8034 return AUGROUP_ERROR;
8035
8036 AUGROUP_NAME(i) = vim_strsave(name);
8037 if (AUGROUP_NAME(i) == NULL)
8038 return AUGROUP_ERROR;
8039 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008040 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008041 }
8042
8043 return i;
8044}
8045
8046 static void
8047au_del_group(name)
8048 char_u *name;
8049{
8050 int i;
8051
8052 i = au_find_group(name);
8053 if (i == AUGROUP_ERROR) /* the group doesn't exist */
8054 EMSG2(_("E367: No such group: \"%s\""), name);
8055 else
8056 {
8057 vim_free(AUGROUP_NAME(i));
8058 AUGROUP_NAME(i) = NULL;
8059 }
8060}
8061
8062/*
8063 * Find the ID of an autocmd group name.
8064 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8065 */
8066 static int
8067au_find_group(name)
8068 char_u *name;
8069{
8070 int i;
8071
8072 for (i = 0; i < augroups.ga_len; ++i)
8073 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
8074 return i;
8075 return AUGROUP_ERROR;
8076}
8077
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008078/*
8079 * Return TRUE if augroup "name" exists.
8080 */
8081 int
8082au_has_group(name)
8083 char_u *name;
8084{
8085 return au_find_group(name) != AUGROUP_ERROR;
8086}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008087
Bram Moolenaar071d4272004-06-13 20:20:40 +00008088/*
8089 * ":augroup {name}".
8090 */
8091 void
8092do_augroup(arg, del_group)
8093 char_u *arg;
8094 int del_group;
8095{
8096 int i;
8097
8098 if (del_group)
8099 {
8100 if (*arg == NUL)
8101 EMSG(_(e_argreq));
8102 else
8103 au_del_group(arg);
8104 }
8105 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
8106 current_augroup = AUGROUP_DEFAULT;
8107 else if (*arg) /* ":aug xxx": switch to group xxx */
8108 {
8109 i = au_new_group(arg);
8110 if (i != AUGROUP_ERROR)
8111 current_augroup = i;
8112 }
8113 else /* ":aug": list the group names */
8114 {
8115 msg_start();
8116 for (i = 0; i < augroups.ga_len; ++i)
8117 {
8118 if (AUGROUP_NAME(i) != NULL)
8119 {
8120 msg_puts(AUGROUP_NAME(i));
8121 msg_puts((char_u *)" ");
8122 }
8123 }
8124 msg_clr_eos();
8125 msg_end();
8126 }
8127}
8128
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008129#if defined(EXITFREE) || defined(PROTO)
8130 void
8131free_all_autocmds()
8132{
8133 for (current_augroup = -1; current_augroup < augroups.ga_len;
8134 ++current_augroup)
8135 do_autocmd((char_u *)"", TRUE);
8136 ga_clear_strings(&augroups);
8137}
8138#endif
8139
Bram Moolenaar071d4272004-06-13 20:20:40 +00008140/*
8141 * Return the event number for event name "start".
8142 * Return NUM_EVENTS if the event name was not found.
8143 * Return a pointer to the next event name in "end".
8144 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008145 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00008146event_name2nr(start, end)
8147 char_u *start;
8148 char_u **end;
8149{
8150 char_u *p;
8151 int i;
8152 int len;
8153
8154 /* the event name ends with end of line, a blank or a comma */
8155 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
8156 ;
8157 for (i = 0; event_names[i].name != NULL; ++i)
8158 {
8159 len = (int)STRLEN(event_names[i].name);
8160 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
8161 break;
8162 }
8163 if (*p == ',')
8164 ++p;
8165 *end = p;
8166 if (event_names[i].name == NULL)
8167 return NUM_EVENTS;
8168 return event_names[i].event;
8169}
8170
8171/*
8172 * Return the name for event "event".
8173 */
8174 static char_u *
8175event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008176 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008177{
8178 int i;
8179
8180 for (i = 0; event_names[i].name != NULL; ++i)
8181 if (event_names[i].event == event)
8182 return (char_u *)event_names[i].name;
8183 return (char_u *)"Unknown";
8184}
8185
8186/*
8187 * Scan over the events. "*" stands for all events.
8188 */
8189 static char_u *
8190find_end_event(arg, have_group)
8191 char_u *arg;
8192 int have_group; /* TRUE when group name was found */
8193{
8194 char_u *pat;
8195 char_u *p;
8196
8197 if (*arg == '*')
8198 {
8199 if (arg[1] && !vim_iswhite(arg[1]))
8200 {
8201 EMSG2(_("E215: Illegal character after *: %s"), arg);
8202 return NULL;
8203 }
8204 pat = arg + 1;
8205 }
8206 else
8207 {
8208 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
8209 {
8210 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
8211 {
8212 if (have_group)
8213 EMSG2(_("E216: No such event: %s"), pat);
8214 else
8215 EMSG2(_("E216: No such group or event: %s"), pat);
8216 return NULL;
8217 }
8218 }
8219 }
8220 return pat;
8221}
8222
8223/*
8224 * Return TRUE if "event" is included in 'eventignore'.
8225 */
8226 static int
8227event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008228 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008229{
8230 char_u *p = p_ei;
8231
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008232 while (*p != NUL)
8233 {
8234 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8235 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008236 if (event_name2nr(p, &p) == event)
8237 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008238 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008239
8240 return FALSE;
8241}
8242
8243/*
8244 * Return OK when the contents of p_ei is valid, FAIL otherwise.
8245 */
8246 int
8247check_ei()
8248{
8249 char_u *p = p_ei;
8250
Bram Moolenaar071d4272004-06-13 20:20:40 +00008251 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008252 {
8253 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8254 {
8255 p += 3;
8256 if (*p == ',')
8257 ++p;
8258 }
8259 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008260 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008261 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008262
8263 return OK;
8264}
8265
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008266# if defined(FEAT_SYN_HL) || defined(PROTO)
8267
8268/*
8269 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
8270 * buffer loaded into the window. "what" must start with a comma.
8271 * Returns the old value of 'eventignore' in allocated memory.
8272 */
8273 char_u *
8274au_event_disable(what)
8275 char *what;
8276{
8277 char_u *new_ei;
8278 char_u *save_ei;
8279
8280 save_ei = vim_strsave(p_ei);
8281 if (save_ei != NULL)
8282 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008283 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008284 if (new_ei != NULL)
8285 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008286 if (*what == ',' && *p_ei == NUL)
8287 STRCPY(new_ei, what + 1);
8288 else
8289 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008290 set_string_option_direct((char_u *)"ei", -1, new_ei,
8291 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008292 vim_free(new_ei);
8293 }
8294 }
8295 return save_ei;
8296}
8297
8298 void
8299au_event_restore(old_ei)
8300 char_u *old_ei;
8301{
8302 if (old_ei != NULL)
8303 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008304 set_string_option_direct((char_u *)"ei", -1, old_ei,
8305 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008306 vim_free(old_ei);
8307 }
8308}
8309# endif /* FEAT_SYN_HL */
8310
Bram Moolenaar071d4272004-06-13 20:20:40 +00008311/*
8312 * do_autocmd() -- implements the :autocmd command. Can be used in the
8313 * following ways:
8314 *
8315 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8316 * will be automatically executed for <event>
8317 * when editing a file matching <pat>, in
8318 * the current group.
8319 * :autocmd <event> <pat> Show the auto-commands associated with
8320 * <event> and <pat>.
8321 * :autocmd <event> Show the auto-commands associated with
8322 * <event>.
8323 * :autocmd Show all auto-commands.
8324 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
8325 * <event> and <pat>, and add the command
8326 * <cmd>, for the current group.
8327 * :autocmd! <event> <pat> Remove all auto-commands associated with
8328 * <event> and <pat> for the current group.
8329 * :autocmd! <event> Remove all auto-commands associated with
8330 * <event> for the current group.
8331 * :autocmd! Remove ALL auto-commands for the current
8332 * group.
8333 *
8334 * Multiple events and patterns may be given separated by commas. Here are
8335 * some examples:
8336 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8337 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8338 *
8339 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008340 *
8341 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008342 */
8343 void
8344do_autocmd(arg, forceit)
8345 char_u *arg;
8346 int forceit;
8347{
8348 char_u *pat;
8349 char_u *envpat = NULL;
8350 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008351 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008352 int need_free = FALSE;
8353 int nested = FALSE;
8354 int group;
8355
8356 /*
8357 * Check for a legal group name. If not, use AUGROUP_ALL.
8358 */
8359 group = au_get_grouparg(&arg);
8360 if (arg == NULL) /* out of memory */
8361 return;
8362
8363 /*
8364 * Scan over the events.
8365 * If we find an illegal name, return here, don't do anything.
8366 */
8367 pat = find_end_event(arg, group != AUGROUP_ALL);
8368 if (pat == NULL)
8369 return;
8370
8371 /*
8372 * Scan over the pattern. Put a NUL at the end.
8373 */
8374 pat = skipwhite(pat);
8375 cmd = pat;
8376 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
8377 cmd++;
8378 if (*cmd)
8379 *cmd++ = NUL;
8380
8381 /* Expand environment variables in the pattern. Set 'shellslash', we want
8382 * forward slashes here. */
8383 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8384 {
8385#ifdef BACKSLASH_IN_FILENAME
8386 int p_ssl_save = p_ssl;
8387
8388 p_ssl = TRUE;
8389#endif
8390 envpat = expand_env_save(pat);
8391#ifdef BACKSLASH_IN_FILENAME
8392 p_ssl = p_ssl_save;
8393#endif
8394 if (envpat != NULL)
8395 pat = envpat;
8396 }
8397
8398 /*
8399 * Check for "nested" flag.
8400 */
8401 cmd = skipwhite(cmd);
8402 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
8403 {
8404 nested = TRUE;
8405 cmd = skipwhite(cmd + 6);
8406 }
8407
8408 /*
8409 * Find the start of the commands.
8410 * Expand <sfile> in it.
8411 */
8412 if (*cmd != NUL)
8413 {
8414 cmd = expand_sfile(cmd);
8415 if (cmd == NULL) /* some error */
8416 return;
8417 need_free = TRUE;
8418 }
8419
8420 /*
8421 * Print header when showing autocommands.
8422 */
8423 if (!forceit && *cmd == NUL)
8424 {
8425 /* Highlight title */
8426 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
8427 }
8428
8429 /*
8430 * Loop over the events.
8431 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008432 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008433 last_group = AUGROUP_ERROR; /* for listing the group name */
8434 if (*arg == '*' || *arg == NUL)
8435 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008436 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8437 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008438 if (do_autocmd_event(event, pat,
8439 nested, cmd, forceit, group) == FAIL)
8440 break;
8441 }
8442 else
8443 {
8444 while (*arg && !vim_iswhite(*arg))
8445 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8446 nested, cmd, forceit, group) == FAIL)
8447 break;
8448 }
8449
8450 if (need_free)
8451 vim_free(cmd);
8452 vim_free(envpat);
8453}
8454
8455/*
8456 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8457 * The "argp" argument is advanced to the following argument.
8458 *
8459 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8460 */
8461 static int
8462au_get_grouparg(argp)
8463 char_u **argp;
8464{
8465 char_u *group_name;
8466 char_u *p;
8467 char_u *arg = *argp;
8468 int group = AUGROUP_ALL;
8469
8470 p = skiptowhite(arg);
8471 if (p > arg)
8472 {
8473 group_name = vim_strnsave(arg, (int)(p - arg));
8474 if (group_name == NULL) /* out of memory */
8475 return AUGROUP_ERROR;
8476 group = au_find_group(group_name);
8477 if (group == AUGROUP_ERROR)
8478 group = AUGROUP_ALL; /* no match, use all groups */
8479 else
8480 *argp = skipwhite(p); /* match, skip over group name */
8481 vim_free(group_name);
8482 }
8483 return group;
8484}
8485
8486/*
8487 * do_autocmd() for one event.
8488 * If *pat == NUL do for all patterns.
8489 * If *cmd == NUL show entries.
8490 * If forceit == TRUE delete entries.
8491 * If group is not AUGROUP_ALL, only use this group.
8492 */
8493 static int
8494do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008495 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008496 char_u *pat;
8497 int nested;
8498 char_u *cmd;
8499 int forceit;
8500 int group;
8501{
8502 AutoPat *ap;
8503 AutoPat **prev_ap;
8504 AutoCmd *ac;
8505 AutoCmd **prev_ac;
8506 int brace_level;
8507 char_u *endpat;
8508 int findgroup;
8509 int allgroups;
8510 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008511 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008512 int buflocal_nr;
8513 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008514
8515 if (group == AUGROUP_ALL)
8516 findgroup = current_augroup;
8517 else
8518 findgroup = group;
8519 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8520
8521 /*
8522 * Show or delete all patterns for an event.
8523 */
8524 if (*pat == NUL)
8525 {
8526 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8527 {
8528 if (forceit) /* delete the AutoPat, if it's in the current group */
8529 {
8530 if (ap->group == findgroup)
8531 au_remove_pat(ap);
8532 }
8533 else if (group == AUGROUP_ALL || ap->group == group)
8534 show_autocmd(ap, event);
8535 }
8536 }
8537
8538 /*
8539 * Loop through all the specified patterns.
8540 */
8541 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8542 {
8543 /*
8544 * Find end of the pattern.
8545 * Watch out for a comma in braces, like "*.\{obj,o\}".
8546 */
8547 brace_level = 0;
8548 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
8549 || endpat[-1] == '\\'); ++endpat)
8550 {
8551 if (*endpat == '{')
8552 brace_level++;
8553 else if (*endpat == '}')
8554 brace_level--;
8555 }
8556 if (pat == endpat) /* ignore single comma */
8557 continue;
8558 patlen = (int)(endpat - pat);
8559
8560 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008561 * detect special <buflocal[=X]> buffer-local patterns
8562 */
8563 is_buflocal = FALSE;
8564 buflocal_nr = 0;
8565
8566 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
8567 && pat[patlen - 1] == '>')
8568 {
8569 /* Error will be printed only for addition. printing and removing
8570 * will proceed silently. */
8571 is_buflocal = TRUE;
8572 if (patlen == 8)
8573 buflocal_nr = curbuf->b_fnum;
8574 else if (patlen > 9 && pat[7] == '=')
8575 {
8576 /* <buffer=abuf> */
8577 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
8578 buflocal_nr = autocmd_bufnr;
8579 /* <buffer=123> */
8580 else if (skipdigits(pat + 8) == pat + patlen - 1)
8581 buflocal_nr = atoi((char *)pat + 8);
8582 }
8583 }
8584
8585 if (is_buflocal)
8586 {
8587 /* normalize pat into standard "<buffer>#N" form */
8588 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8589 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008590 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008591 }
8592
8593 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008594 * Find AutoPat entries with this pattern.
8595 */
8596 prev_ap = &first_autopat[(int)event];
8597 while ((ap = *prev_ap) != NULL)
8598 {
8599 if (ap->pat != NULL)
8600 {
8601 /* Accept a pattern when:
8602 * - a group was specified and it's that group, or a group was
8603 * not specified and it's the current group, or a group was
8604 * not specified and we are listing
8605 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008606 * - the pattern matches.
8607 * For <buffer[=X]>, this condition works because we normalize
8608 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008609 */
8610 if ((allgroups || ap->group == findgroup)
8611 && ap->patlen == patlen
8612 && STRNCMP(pat, ap->pat, patlen) == 0)
8613 {
8614 /*
8615 * Remove existing autocommands.
8616 * If adding any new autocmd's for this AutoPat, don't
8617 * delete the pattern from the autopat list, append to
8618 * this list.
8619 */
8620 if (forceit)
8621 {
8622 if (*cmd != NUL && ap->next == NULL)
8623 {
8624 au_remove_cmds(ap);
8625 break;
8626 }
8627 au_remove_pat(ap);
8628 }
8629
8630 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008631 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008632 */
8633 else if (*cmd == NUL)
8634 show_autocmd(ap, event);
8635
8636 /*
8637 * Add autocmd to this autopat, if it's the last one.
8638 */
8639 else if (ap->next == NULL)
8640 break;
8641 }
8642 }
8643 prev_ap = &ap->next;
8644 }
8645
8646 /*
8647 * Add a new command.
8648 */
8649 if (*cmd != NUL)
8650 {
8651 /*
8652 * If the pattern we want to add a command to does appear at the
8653 * end of the list (or not is not in the list at all), add the
8654 * pattern at the end of the list.
8655 */
8656 if (ap == NULL)
8657 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008658 /* refuse to add buffer-local ap if buffer number is invalid */
8659 if (is_buflocal && (buflocal_nr == 0
8660 || buflist_findnr(buflocal_nr) == NULL))
8661 {
8662 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
8663 buflocal_nr);
8664 return FAIL;
8665 }
8666
Bram Moolenaar071d4272004-06-13 20:20:40 +00008667 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8668 if (ap == NULL)
8669 return FAIL;
8670 ap->pat = vim_strnsave(pat, patlen);
8671 ap->patlen = patlen;
8672 if (ap->pat == NULL)
8673 {
8674 vim_free(ap);
8675 return FAIL;
8676 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008677
8678 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008679 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008680 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008681 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008682 }
8683 else
8684 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008685 char_u *reg_pat;
8686
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008687 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008688 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008689 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008690 if (reg_pat != NULL)
8691 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008692 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008693 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008694 {
8695 vim_free(ap->pat);
8696 vim_free(ap);
8697 return FAIL;
8698 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008699 }
8700 ap->cmds = NULL;
8701 *prev_ap = ap;
8702 ap->next = NULL;
8703 if (group == AUGROUP_ALL)
8704 ap->group = current_augroup;
8705 else
8706 ap->group = group;
8707 }
8708
8709 /*
8710 * Add the autocmd at the end of the AutoCmd list.
8711 */
8712 prev_ac = &(ap->cmds);
8713 while ((ac = *prev_ac) != NULL)
8714 prev_ac = &ac->next;
8715 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8716 if (ac == NULL)
8717 return FAIL;
8718 ac->cmd = vim_strsave(cmd);
8719#ifdef FEAT_EVAL
8720 ac->scriptID = current_SID;
8721#endif
8722 if (ac->cmd == NULL)
8723 {
8724 vim_free(ac);
8725 return FAIL;
8726 }
8727 ac->next = NULL;
8728 *prev_ac = ac;
8729 ac->nested = nested;
8730 }
8731 }
8732
8733 au_cleanup(); /* may really delete removed patterns/commands now */
8734 return OK;
8735}
8736
8737/*
8738 * Implementation of ":doautocmd [group] event [fname]".
8739 * Return OK for success, FAIL for failure;
8740 */
8741 int
8742do_doautocmd(arg, do_msg)
8743 char_u *arg;
8744 int do_msg; /* give message for no matching autocmds? */
8745{
8746 char_u *fname;
8747 int nothing_done = TRUE;
8748 int group;
8749
8750 /*
8751 * Check for a legal group name. If not, use AUGROUP_ALL.
8752 */
8753 group = au_get_grouparg(&arg);
8754 if (arg == NULL) /* out of memory */
8755 return FAIL;
8756
8757 if (*arg == '*')
8758 {
8759 EMSG(_("E217: Can't execute autocommands for ALL events"));
8760 return FAIL;
8761 }
8762
8763 /*
8764 * Scan over the events.
8765 * If we find an illegal name, return here, don't do anything.
8766 */
8767 fname = find_end_event(arg, group != AUGROUP_ALL);
8768 if (fname == NULL)
8769 return FAIL;
8770
8771 fname = skipwhite(fname);
8772
8773 /*
8774 * Loop over the events.
8775 */
8776 while (*arg && !vim_iswhite(*arg))
8777 if (apply_autocmds_group(event_name2nr(arg, &arg),
8778 fname, NULL, TRUE, group, curbuf, NULL))
8779 nothing_done = FALSE;
8780
8781 if (nothing_done && do_msg)
8782 MSG(_("No matching autocommands"));
8783
8784#ifdef FEAT_EVAL
8785 return aborting() ? FAIL : OK;
8786#else
8787 return OK;
8788#endif
8789}
8790
8791/*
8792 * ":doautoall": execute autocommands for each loaded buffer.
8793 */
8794 void
8795ex_doautoall(eap)
8796 exarg_T *eap;
8797{
8798 int retval;
8799 aco_save_T aco;
8800 buf_T *buf;
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008801 char_u *arg = eap->arg;
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008802 int call_do_modelines = check_nomodeline(&arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008803
8804 /*
8805 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8806 * equal to curbuf, but for some buffers there may not be a window.
8807 * So we change the buffer for the current window for a moment. This
8808 * gives problems when the autocommands make changes to the list of
8809 * buffers or windows...
8810 */
8811 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8812 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008813 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008814 {
8815 /* find a window for this buffer and save some values */
8816 aucmd_prepbuf(&aco, buf);
8817
8818 /* execute the autocommands for this buffer */
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008819 retval = do_doautocmd(arg, FALSE);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008820
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008821 if (call_do_modelines)
8822 {
8823 /* Execute the modeline settings, but don't set window-local
8824 * options if we are using the current window for another
8825 * buffer. */
8826 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
8827 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008828
8829 /* restore the current window */
8830 aucmd_restbuf(&aco);
8831
8832 /* stop if there is some error or buffer was deleted */
8833 if (retval == FAIL || !buf_valid(buf))
8834 break;
8835 }
8836 }
8837
8838 check_cursor(); /* just in case lines got deleted */
8839}
8840
8841/*
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008842 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
8843 * return TRUE and advance *argp to after it.
8844 * Thus return TRUE when do_modelines() should be called.
8845 */
8846 int
8847check_nomodeline(argp)
8848 char_u **argp;
8849{
8850 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
8851 {
8852 *argp = skipwhite(*argp + 12);
8853 return FALSE;
8854 }
8855 return TRUE;
8856}
8857
8858/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008859 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008860 * Search for a visible window containing the current buffer. If there isn't
8861 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008862 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008863 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008864 */
8865 void
8866aucmd_prepbuf(aco, buf)
8867 aco_save_T *aco; /* structure to save values in */
8868 buf_T *buf; /* new curbuf */
8869{
8870 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008871#ifdef FEAT_WINDOWS
8872 int save_ea;
8873#endif
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008874#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008875 int save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008876#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008877
8878 /* Find a window that is for the new buffer */
8879 if (buf == curbuf) /* be quick when buf is curbuf */
8880 win = curwin;
8881 else
8882#ifdef FEAT_WINDOWS
8883 for (win = firstwin; win != NULL; win = win->w_next)
8884 if (win->w_buffer == buf)
8885 break;
8886#else
8887 win = NULL;
8888#endif
8889
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008890 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
8891 * back to using the current window. */
8892 if (win == NULL && aucmd_win == NULL)
8893 {
8894 win_alloc_aucmd_win();
8895 if (aucmd_win == NULL)
8896 win = curwin;
8897 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008898 if (win == NULL && aucmd_win_used)
8899 /* Strange recursive autocommand, fall back to using the current
8900 * window. Expect a few side effects... */
8901 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008902
8903 aco->save_curwin = curwin;
8904 aco->save_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008905 if (win != NULL)
8906 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008907 /* There is a window for "buf" in the current tab page, make it the
8908 * curwin. This is preferred, it has the least side effects (esp. if
8909 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008910 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008911 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008912 }
8913 else
8914 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008915 /* There is no window for "buf", use "aucmd_win". To minimize the side
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02008916 * effects, insert it in the current tab page.
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008917 * Anything related to a window (e.g., setting folds) may have
8918 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008919 aco->use_aucmd_win = TRUE;
8920 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008921 aucmd_win->w_buffer = buf;
Bram Moolenaarcdddaa42010-06-07 23:07:44 +02008922 aucmd_win->w_s = &buf->b_s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008923 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008924 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008925
8926 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
8927 * win_enter_ext(). */
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008928 vim_free(aucmd_win->w_localdir);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008929 aucmd_win->w_localdir = NULL;
8930 aco->globaldir = globaldir;
8931 globaldir = NULL;
8932
Bram Moolenaar071d4272004-06-13 20:20:40 +00008933
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008934#ifdef FEAT_WINDOWS
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008935 /* Split the current window, put the aucmd_win in the upper half.
8936 * We don't want the BufEnter or WinEnter autocommands. */
8937 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008938 make_snapshot(SNAP_AUCMD_IDX);
8939 save_ea = p_ea;
8940 p_ea = FALSE;
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008941
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008942# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008943 /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
8944 save_acd = p_acd;
8945 p_acd = FALSE;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008946# endif
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008947
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008948 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
8949 (void)win_comp_pos(); /* recompute window positions */
8950 p_ea = save_ea;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008951# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008952 p_acd = save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008953# endif
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008954 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008955#endif
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008956 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008958 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008959 aco->new_curwin = curwin;
8960 aco->new_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008961}
8962
8963/*
8964 * Cleanup after executing autocommands for a (hidden) buffer.
8965 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008966 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008967 */
8968 void
8969aucmd_restbuf(aco)
8970 aco_save_T *aco; /* structure holding saved values */
8971{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008972#ifdef FEAT_WINDOWS
8973 int dummy;
8974#endif
8975
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008976 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008977 {
8978 --curbuf->b_nwindows;
8979#ifdef FEAT_WINDOWS
8980 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008981 * page. Do not trigger autocommands here. */
8982 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008983 if (curwin != aucmd_win)
8984 {
8985 tabpage_T *tp;
8986 win_T *wp;
8987
8988 FOR_ALL_TAB_WINDOWS(tp, wp)
8989 {
8990 if (wp == aucmd_win)
8991 {
8992 if (tp != curtab)
Bram Moolenaar49e649f2013-05-06 04:50:35 +02008993 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008994 win_goto(aucmd_win);
Bram Moolenaar28f29082012-02-11 23:45:37 +01008995 goto win_found;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008996 }
8997 }
8998 }
Bram Moolenaar28f29082012-02-11 23:45:37 +01008999win_found:
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009000
9001 /* Remove the window and frame from the tree of frames. */
9002 (void)winframe_remove(curwin, &dummy, NULL);
9003 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009004 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009005 last_status(FALSE); /* may need to remove last status line */
9006 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
9007 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009008 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009009
9010 if (win_valid(aco->save_curwin))
9011 curwin = aco->save_curwin;
9012 else
9013 /* Hmm, original window disappeared. Just use the first one. */
9014 curwin = firstwin;
9015# ifdef FEAT_EVAL
Bram Moolenaar429fa852013-04-15 12:27:36 +02009016 vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
9017 hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009018# endif
9019#else
9020 curwin = aco->save_curwin;
9021#endif
9022 curbuf = curwin->w_buffer;
9023
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009024 vim_free(globaldir);
9025 globaldir = aco->globaldir;
9026
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009027 /* the buffer contents may have changed */
9028 check_cursor();
9029 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
9030 {
9031 curwin->w_topline = curbuf->b_ml.ml_line_count;
9032#ifdef FEAT_DIFF
9033 curwin->w_topfill = 0;
9034#endif
9035 }
9036#if defined(FEAT_GUI)
9037 /* Hide the scrollbars from the aucmd_win and update. */
9038 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
9039 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
9040 gui_may_update_scrollbars();
9041#endif
9042 }
9043 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009044 {
9045 /* restore curwin */
9046#ifdef FEAT_WINDOWS
9047 if (win_valid(aco->save_curwin))
9048#endif
9049 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009050 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009051 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009052 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009053 if (curwin == aco->new_curwin
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009054 && curbuf != aco->new_curbuf
9055 && buf_valid(aco->new_curbuf)
9056 && aco->new_curbuf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009057 {
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009058# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
9059 if (curwin->w_s == &curbuf->b_s)
9060 curwin->w_s = &aco->new_curbuf->b_s;
9061# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009062 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009063 curbuf = aco->new_curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009064 curwin->w_buffer = curbuf;
9065 ++curbuf->b_nwindows;
9066 }
9067
9068 curwin = aco->save_curwin;
9069 curbuf = curwin->w_buffer;
9070 }
9071 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009072}
9073
9074static int autocmd_nested = FALSE;
9075
9076/*
9077 * Execute autocommands for "event" and file name "fname".
9078 * Return TRUE if some commands were executed.
9079 */
9080 int
9081apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009082 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083 char_u *fname; /* NULL or empty means use actual file name */
9084 char_u *fname_io; /* fname to use for <afile> on cmdline */
9085 int force; /* when TRUE, ignore autocmd_busy */
9086 buf_T *buf; /* buffer for <abuf> */
9087{
9088 return apply_autocmds_group(event, fname, fname_io, force,
9089 AUGROUP_ALL, buf, NULL);
9090}
9091
9092/*
9093 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
9094 * setting v:filearg.
9095 */
9096 static int
9097apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009098 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009099 char_u *fname;
9100 char_u *fname_io;
9101 int force;
9102 buf_T *buf;
9103 exarg_T *eap;
9104{
9105 return apply_autocmds_group(event, fname, fname_io, force,
9106 AUGROUP_ALL, buf, eap);
9107}
9108
9109/*
9110 * Like apply_autocmds(), but handles the caller's retval. If the script
9111 * processing is being aborted or if retval is FAIL when inside a try
9112 * conditional, no autocommands are executed. If otherwise the autocommands
9113 * cause the script to be aborted, retval is set to FAIL.
9114 */
9115 int
9116apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009117 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009118 char_u *fname; /* NULL or empty means use actual file name */
9119 char_u *fname_io; /* fname to use for <afile> on cmdline */
9120 int force; /* when TRUE, ignore autocmd_busy */
9121 buf_T *buf; /* buffer for <abuf> */
9122 int *retval; /* pointer to caller's retval */
9123{
9124 int did_cmd;
9125
Bram Moolenaar1e015462005-09-25 22:16:38 +00009126#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009127 if (should_abort(*retval))
9128 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00009129#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009130
9131 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
9132 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00009133 if (did_cmd
9134#ifdef FEAT_EVAL
9135 && aborting()
9136#endif
9137 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00009138 *retval = FAIL;
9139 return did_cmd;
9140}
9141
Bram Moolenaard35f9712005-12-18 22:02:33 +00009142/*
9143 * Return TRUE when there is a CursorHold autocommand defined.
9144 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009145 int
9146has_cursorhold()
9147{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009148 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
9149 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009150}
Bram Moolenaard35f9712005-12-18 22:02:33 +00009151
9152/*
9153 * Return TRUE if the CursorHold event can be triggered.
9154 */
9155 int
9156trigger_cursorhold()
9157{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009158 int state;
9159
Bram Moolenaar05334432011-07-20 18:29:39 +02009160 if (!did_cursorhold
9161 && has_cursorhold()
9162 && !Recording
9163 && typebuf.tb_len == 0
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00009164#ifdef FEAT_INS_EXPAND
9165 && !ins_compl_active()
9166#endif
9167 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00009168 {
9169 state = get_real_state();
9170 if (state == NORMAL_BUSY || (state & INSERT) != 0)
9171 return TRUE;
9172 }
9173 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00009174}
Bram Moolenaar754b5602006-02-09 23:53:20 +00009175
9176/*
9177 * Return TRUE when there is a CursorMoved autocommand defined.
9178 */
9179 int
9180has_cursormoved()
9181{
9182 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
9183}
9184
9185/*
9186 * Return TRUE when there is a CursorMovedI autocommand defined.
9187 */
9188 int
9189has_cursormovedI()
9190{
9191 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
9192}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009193
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009194/*
Bram Moolenaar186628f2013-03-19 13:33:23 +01009195 * Return TRUE when there is a TextChanged autocommand defined.
9196 */
9197 int
9198has_textchanged()
9199{
9200 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
9201}
9202
9203/*
9204 * Return TRUE when there is a TextChangedI autocommand defined.
9205 */
9206 int
9207has_textchangedI()
9208{
9209 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
9210}
9211
9212/*
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009213 * Return TRUE when there is an InsertCharPre autocommand defined.
9214 */
9215 int
9216has_insertcharpre()
9217{
9218 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
9219}
9220
Bram Moolenaar071d4272004-06-13 20:20:40 +00009221 static int
9222apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009223 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009224 char_u *fname; /* NULL or empty means use actual file name */
9225 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
9226 use fname */
9227 int force; /* when TRUE, ignore autocmd_busy */
9228 int group; /* group ID, or AUGROUP_ALL */
9229 buf_T *buf; /* buffer for <abuf> */
9230 exarg_T *eap; /* command arguments */
9231{
9232 char_u *sfname = NULL; /* short file name */
9233 char_u *tail;
9234 int save_changed;
9235 buf_T *old_curbuf;
9236 int retval = FALSE;
9237 char_u *save_sourcing_name;
9238 linenr_T save_sourcing_lnum;
9239 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009240 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009241 int save_autocmd_bufnr;
9242 char_u *save_autocmd_match;
9243 int save_autocmd_busy;
9244 int save_autocmd_nested;
9245 static int nesting = 0;
9246 AutoPatCmd patcmd;
9247 AutoPat *ap;
9248#ifdef FEAT_EVAL
9249 scid_T save_current_SID;
9250 void *save_funccalp;
9251 char_u *save_cmdarg;
9252 long save_cmdbang;
9253#endif
9254 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00009255#ifdef FEAT_PROFILE
9256 proftime_T wait_time;
9257#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009258
9259 /*
9260 * Quickly return if there are no autocommands for this event or
9261 * autocommands are blocked.
9262 */
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009263 if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009264 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009265
9266 /*
9267 * When autocommands are busy, new autocommands are only executed when
9268 * explicitly enabled with the "nested" flag.
9269 */
9270 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009271 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009272
9273#ifdef FEAT_EVAL
9274 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00009275 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00009276 * occurred or an exception was thrown but not caught.
9277 */
9278 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009279 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009280#endif
9281
9282 /*
9283 * FileChangedShell never nests, because it can create an endless loop.
9284 */
Bram Moolenaar56718732006-03-15 22:53:57 +00009285 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
9286 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009287 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009288
9289 /*
9290 * Ignore events in 'eventignore'.
9291 */
9292 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009293 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009294
9295 /*
9296 * Allow nesting of autocommands, but restrict the depth, because it's
9297 * possible to create an endless loop.
9298 */
9299 if (nesting == 10)
9300 {
9301 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009302 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009303 }
9304
9305 /*
9306 * Check if these autocommands are disabled. Used when doing ":all" or
9307 * ":ball".
9308 */
9309 if ( (autocmd_no_enter
9310 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
9311 || (autocmd_no_leave
9312 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009313 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009314
9315 /*
9316 * Save the autocmd_* variables and info about the current buffer.
9317 */
9318 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009319 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009320 save_autocmd_bufnr = autocmd_bufnr;
9321 save_autocmd_match = autocmd_match;
9322 save_autocmd_busy = autocmd_busy;
9323 save_autocmd_nested = autocmd_nested;
9324 save_changed = curbuf->b_changed;
9325 old_curbuf = curbuf;
9326
9327 /*
9328 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00009329 * Make a copy to avoid that changing a buffer name or directory makes it
9330 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009331 */
9332 if (fname_io == NULL)
9333 {
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009334 if (event == EVENT_COLORSCHEME)
9335 autocmd_fname = NULL;
9336 else if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009337 autocmd_fname = fname;
9338 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009339 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009340 else
9341 autocmd_fname = NULL;
9342 }
9343 else
9344 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009345 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009346 autocmd_fname = vim_strsave(autocmd_fname);
9347 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009348
9349 /*
9350 * Set the buffer number to be used for <abuf>.
9351 */
9352 if (buf == NULL)
9353 autocmd_bufnr = 0;
9354 else
9355 autocmd_bufnr = buf->b_fnum;
9356
9357 /*
9358 * When the file name is NULL or empty, use the file name of buffer "buf".
9359 * Always use the full path of the file name to match with, in case
9360 * "allow_dirs" is set.
9361 */
9362 if (fname == NULL || *fname == NUL)
9363 {
9364 if (buf == NULL)
9365 fname = NULL;
9366 else
9367 {
9368#ifdef FEAT_SYN_HL
9369 if (event == EVENT_SYNTAX)
9370 fname = buf->b_p_syn;
9371 else
9372#endif
9373 if (event == EVENT_FILETYPE)
9374 fname = buf->b_p_ft;
9375 else
9376 {
9377 if (buf->b_sfname != NULL)
9378 sfname = vim_strsave(buf->b_sfname);
9379 fname = buf->b_ffname;
9380 }
9381 }
9382 if (fname == NULL)
9383 fname = (char_u *)"";
9384 fname = vim_strsave(fname); /* make a copy, so we can change it */
9385 }
9386 else
9387 {
9388 sfname = vim_strsave(fname);
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009389 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
9390 * ColorScheme or QuickFixCmd* */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009391 if (event == EVENT_FILETYPE
9392 || event == EVENT_SYNTAX
Bram Moolenaar5135d462009-04-29 16:03:38 +00009393 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009394 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009395 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009396 || event == EVENT_QUICKFIXCMDPRE
Bram Moolenaarb95186f2013-11-28 18:53:52 +01009397 || event == EVENT_COLORSCHEME
Bram Moolenaar7c626922005-02-07 22:01:03 +00009398 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009399 fname = vim_strsave(fname);
9400 else
9401 fname = FullName_save(fname, FALSE);
9402 }
9403 if (fname == NULL) /* out of memory */
9404 {
9405 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009406 retval = FALSE;
9407 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009408 }
9409
9410#ifdef BACKSLASH_IN_FILENAME
9411 /*
9412 * Replace all backslashes with forward slashes. This makes the
9413 * autocommand patterns portable between Unix and MS-DOS.
9414 */
9415 if (sfname != NULL)
9416 forward_slash(sfname);
9417 forward_slash(fname);
9418#endif
9419
9420#ifdef VMS
9421 /* remove version for correct match */
9422 if (sfname != NULL)
9423 vms_remove_version(sfname);
9424 vms_remove_version(fname);
9425#endif
9426
9427 /*
9428 * Set the name to be used for <amatch>.
9429 */
9430 autocmd_match = fname;
9431
9432
9433 /* Don't redraw while doing auto commands. */
9434 ++RedrawingDisabled;
9435 save_sourcing_name = sourcing_name;
9436 sourcing_name = NULL; /* don't free this one */
9437 save_sourcing_lnum = sourcing_lnum;
9438 sourcing_lnum = 0; /* no line number here */
9439
9440#ifdef FEAT_EVAL
9441 save_current_SID = current_SID;
9442
Bram Moolenaar05159a02005-02-26 23:04:13 +00009443# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009444 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009445 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9446# endif
9447
Bram Moolenaar071d4272004-06-13 20:20:40 +00009448 /* Don't use local function variables, if called from a function */
9449 save_funccalp = save_funccal();
9450#endif
9451
9452 /*
9453 * When starting to execute autocommands, save the search patterns.
9454 */
9455 if (!autocmd_busy)
9456 {
9457 save_search_patterns();
9458 saveRedobuff();
9459 did_filetype = keep_filetype;
9460 }
9461
9462 /*
9463 * Note that we are applying autocmds. Some commands need to know.
9464 */
9465 autocmd_busy = TRUE;
9466 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9467 ++nesting; /* see matching decrement below */
9468
9469 /* Remember that FileType was triggered. Used for did_filetype(). */
9470 if (event == EVENT_FILETYPE)
9471 did_filetype = TRUE;
9472
9473 tail = gettail(fname);
9474
9475 /* Find first autocommand that matches */
9476 patcmd.curpat = first_autopat[(int)event];
9477 patcmd.nextcmd = NULL;
9478 patcmd.group = group;
9479 patcmd.fname = fname;
9480 patcmd.sfname = sfname;
9481 patcmd.tail = tail;
9482 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009483 patcmd.arg_bufnr = autocmd_bufnr;
9484 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009485 auto_next_pat(&patcmd, FALSE);
9486
9487 /* found one, start executing the autocommands */
9488 if (patcmd.curpat != NULL)
9489 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009490 /* add to active_apc_list */
9491 patcmd.next = active_apc_list;
9492 active_apc_list = &patcmd;
9493
Bram Moolenaar071d4272004-06-13 20:20:40 +00009494#ifdef FEAT_EVAL
9495 /* set v:cmdarg (only when there is a matching pattern) */
9496 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
9497 if (eap != NULL)
9498 {
9499 save_cmdarg = set_cmdarg(eap, NULL);
9500 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9501 }
9502 else
9503 save_cmdarg = NULL; /* avoid gcc warning */
9504#endif
9505 retval = TRUE;
9506 /* mark the last pattern, to avoid an endless loop when more patterns
9507 * are added when executing autocommands */
9508 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9509 ap->last = FALSE;
9510 ap->last = TRUE;
9511 check_lnums(TRUE); /* make sure cursor and topline are valid */
9512 do_cmdline(NULL, getnextac, (void *)&patcmd,
9513 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9514#ifdef FEAT_EVAL
9515 if (eap != NULL)
9516 {
9517 (void)set_cmdarg(NULL, save_cmdarg);
9518 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9519 }
9520#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009521 /* delete from active_apc_list */
9522 if (active_apc_list == &patcmd) /* just in case */
9523 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009524 }
9525
9526 --RedrawingDisabled;
9527 autocmd_busy = save_autocmd_busy;
9528 filechangeshell_busy = FALSE;
9529 autocmd_nested = save_autocmd_nested;
9530 vim_free(sourcing_name);
9531 sourcing_name = save_sourcing_name;
9532 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009533 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009534 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009535 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009536 autocmd_bufnr = save_autocmd_bufnr;
9537 autocmd_match = save_autocmd_match;
9538#ifdef FEAT_EVAL
9539 current_SID = save_current_SID;
9540 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00009541# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009542 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009543 prof_child_exit(&wait_time);
9544# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009545#endif
9546 vim_free(fname);
9547 vim_free(sfname);
9548 --nesting; /* see matching increment above */
9549
9550 /*
9551 * When stopping to execute autocommands, restore the search patterns and
Bram Moolenaar3be85852014-06-12 14:01:31 +02009552 * the redo buffer. Free any buffers in the au_pending_free_buf list and
9553 * free any windows in the au_pending_free_win list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009554 */
9555 if (!autocmd_busy)
9556 {
9557 restore_search_patterns();
9558 restoreRedobuff();
9559 did_filetype = FALSE;
Bram Moolenaar4c7ab1b2014-04-06 20:45:43 +02009560 while (au_pending_free_buf != NULL)
9561 {
9562 buf_T *b = au_pending_free_buf->b_next;
9563 vim_free(au_pending_free_buf);
9564 au_pending_free_buf = b;
9565 }
Bram Moolenaar3be85852014-06-12 14:01:31 +02009566 while (au_pending_free_win != NULL)
9567 {
9568 win_T *w = au_pending_free_win->w_next;
9569 vim_free(au_pending_free_win);
9570 au_pending_free_win = w;
9571 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009572 }
9573
9574 /*
9575 * Some events don't set or reset the Changed flag.
9576 * Check if still in the same buffer!
9577 */
9578 if (curbuf == old_curbuf
9579 && (event == EVENT_BUFREADPOST
9580 || event == EVENT_BUFWRITEPOST
9581 || event == EVENT_FILEAPPENDPOST
9582 || event == EVENT_VIMLEAVE
9583 || event == EVENT_VIMLEAVEPRE))
9584 {
9585#ifdef FEAT_TITLE
9586 if (curbuf->b_changed != save_changed)
9587 need_maketitle = TRUE;
9588#endif
9589 curbuf->b_changed = save_changed;
9590 }
9591
9592 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009593
9594BYPASS_AU:
9595 /* When wiping out a buffer make sure all its buffer-local autocommands
9596 * are deleted. */
9597 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9598 aubuflocal_remove(buf);
9599
Bram Moolenaar071d4272004-06-13 20:20:40 +00009600 return retval;
9601}
9602
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009603# ifdef FEAT_EVAL
9604static char_u *old_termresponse = NULL;
9605# endif
9606
9607/*
9608 * Block triggering autocommands until unblock_autocmd() is called.
9609 * Can be used recursively, so long as it's symmetric.
9610 */
9611 void
9612block_autocmds()
9613{
9614# ifdef FEAT_EVAL
9615 /* Remember the value of v:termresponse. */
9616 if (autocmd_blocked == 0)
9617 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9618# endif
9619 ++autocmd_blocked;
9620}
9621
9622 void
9623unblock_autocmds()
9624{
9625 --autocmd_blocked;
9626
9627# ifdef FEAT_EVAL
9628 /* When v:termresponse was set while autocommands were blocked, trigger
9629 * the autocommands now. Esp. useful when executing a shell command
9630 * during startup (vimdiff). */
9631 if (autocmd_blocked == 0
9632 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9633 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9634# endif
9635}
9636
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009637 int
9638is_autocmd_blocked()
9639{
9640 return autocmd_blocked != 0;
9641}
9642
Bram Moolenaar071d4272004-06-13 20:20:40 +00009643/*
9644 * Find next autocommand pattern that matches.
9645 */
9646 static void
9647auto_next_pat(apc, stop_at_last)
9648 AutoPatCmd *apc;
9649 int stop_at_last; /* stop when 'last' flag is set */
9650{
9651 AutoPat *ap;
9652 AutoCmd *cp;
9653 char_u *name;
9654 char *s;
9655
9656 vim_free(sourcing_name);
9657 sourcing_name = NULL;
9658
9659 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9660 {
9661 apc->curpat = NULL;
9662
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009663 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009664 * the group matches. For buffer-local autocommands only check the
9665 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009666 if (ap->pat != NULL && ap->cmds != NULL
9667 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9668 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009669 /* execution-condition */
9670 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009671 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
9672 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009673 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009674 {
9675 name = event_nr2name(apc->event);
9676 s = _("%s Auto commands for \"%s\"");
9677 sourcing_name = alloc((unsigned)(STRLEN(s)
9678 + STRLEN(name) + ap->patlen + 1));
9679 if (sourcing_name != NULL)
9680 {
9681 sprintf((char *)sourcing_name, s,
9682 (char *)name, (char *)ap->pat);
9683 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009684 {
9685 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009686 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009687 verbose_leave();
9688 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009689 }
9690
9691 apc->curpat = ap;
9692 apc->nextcmd = ap->cmds;
9693 /* mark last command */
9694 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9695 cp->last = FALSE;
9696 cp->last = TRUE;
9697 }
9698 line_breakcheck();
9699 if (apc->curpat != NULL) /* found a match */
9700 break;
9701 }
9702 if (stop_at_last && ap->last)
9703 break;
9704 }
9705}
9706
9707/*
9708 * Get next autocommand command.
9709 * Called by do_cmdline() to get the next line for ":if".
9710 * Returns allocated string, or NULL for end of autocommands.
9711 */
Bram Moolenaar21691f82012-12-05 19:13:18 +01009712 char_u *
Bram Moolenaar071d4272004-06-13 20:20:40 +00009713getnextac(c, cookie, indent)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009714 int c UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009715 void *cookie;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009716 int indent UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009717{
9718 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9719 char_u *retval;
9720 AutoCmd *ac;
9721
9722 /* Can be called again after returning the last line. */
9723 if (acp->curpat == NULL)
9724 return NULL;
9725
9726 /* repeat until we find an autocommand to execute */
9727 for (;;)
9728 {
9729 /* skip removed commands */
9730 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9731 if (acp->nextcmd->last)
9732 acp->nextcmd = NULL;
9733 else
9734 acp->nextcmd = acp->nextcmd->next;
9735
9736 if (acp->nextcmd != NULL)
9737 break;
9738
9739 /* at end of commands, find next pattern that matches */
9740 if (acp->curpat->last)
9741 acp->curpat = NULL;
9742 else
9743 acp->curpat = acp->curpat->next;
9744 if (acp->curpat != NULL)
9745 auto_next_pat(acp, TRUE);
9746 if (acp->curpat == NULL)
9747 return NULL;
9748 }
9749
9750 ac = acp->nextcmd;
9751
9752 if (p_verbose >= 9)
9753 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009754 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009755 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009756 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009757 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009758 }
9759 retval = vim_strsave(ac->cmd);
9760 autocmd_nested = ac->nested;
9761#ifdef FEAT_EVAL
9762 current_SID = ac->scriptID;
9763#endif
9764 if (ac->last)
9765 acp->nextcmd = NULL;
9766 else
9767 acp->nextcmd = ac->next;
9768 return retval;
9769}
9770
9771/*
9772 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009773 * To account for buffer-local autocommands, function needs to know
9774 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009775 */
9776 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009777has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009778 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009779 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009780 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009781{
9782 AutoPat *ap;
9783 char_u *fname;
9784 char_u *tail = gettail(sfname);
9785 int retval = FALSE;
9786
9787 fname = FullName_save(sfname, FALSE);
9788 if (fname == NULL)
9789 return FALSE;
9790
9791#ifdef BACKSLASH_IN_FILENAME
9792 /*
9793 * Replace all backslashes with forward slashes. This makes the
9794 * autocommand patterns portable between Unix and MS-DOS.
9795 */
9796 sfname = vim_strsave(sfname);
9797 if (sfname != NULL)
9798 forward_slash(sfname);
9799 forward_slash(fname);
9800#endif
9801
9802 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9803 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009804 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009805 ? match_file_pat(NULL, ap->reg_prog,
9806 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009807 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009808 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009809 {
9810 retval = TRUE;
9811 break;
9812 }
9813
9814 vim_free(fname);
9815#ifdef BACKSLASH_IN_FILENAME
9816 vim_free(sfname);
9817#endif
9818
9819 return retval;
9820}
9821
9822#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9823/*
9824 * Function given to ExpandGeneric() to obtain the list of autocommand group
9825 * names.
9826 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009827 char_u *
9828get_augroup_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009829 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009830 int idx;
9831{
9832 if (idx == augroups.ga_len) /* add "END" add the end */
9833 return (char_u *)"END";
9834 if (idx >= augroups.ga_len) /* end of list */
9835 return NULL;
9836 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
9837 return (char_u *)"";
9838 return AUGROUP_NAME(idx); /* return a name */
9839}
9840
9841static int include_groups = FALSE;
9842
9843 char_u *
9844set_context_in_autocmd(xp, arg, doautocmd)
9845 expand_T *xp;
9846 char_u *arg;
Bram Moolenaard812df62008-11-09 12:46:09 +00009847 int doautocmd; /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009848{
9849 char_u *p;
9850 int group;
9851
9852 /* check for a group name, skip it if present */
9853 include_groups = FALSE;
9854 p = arg;
9855 group = au_get_grouparg(&arg);
9856 if (group == AUGROUP_ERROR)
9857 return NULL;
9858 /* If there only is a group name that's what we expand. */
9859 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
9860 {
9861 arg = p;
9862 group = AUGROUP_ALL;
9863 }
9864
9865 /* skip over event name */
9866 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
9867 if (*p == ',')
9868 arg = p + 1;
9869 if (*p == NUL)
9870 {
9871 if (group == AUGROUP_ALL)
9872 include_groups = TRUE;
9873 xp->xp_context = EXPAND_EVENTS; /* expand event name */
9874 xp->xp_pattern = arg;
9875 return NULL;
9876 }
9877
9878 /* skip over pattern */
9879 arg = skipwhite(p);
9880 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
9881 arg++;
9882 if (*arg)
9883 return arg; /* expand (next) command */
9884
9885 if (doautocmd)
9886 xp->xp_context = EXPAND_FILES; /* expand file names */
9887 else
9888 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9889 return NULL;
9890}
9891
9892/*
9893 * Function given to ExpandGeneric() to obtain the list of event names.
9894 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009895 char_u *
9896get_event_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009897 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009898 int idx;
9899{
9900 if (idx < augroups.ga_len) /* First list group names, if wanted */
9901 {
9902 if (!include_groups || AUGROUP_NAME(idx) == NULL)
9903 return (char_u *)""; /* skip deleted entries */
9904 return AUGROUP_NAME(idx); /* return a name */
9905 }
9906 return (char_u *)event_names[idx - augroups.ga_len].name;
9907}
9908
9909#endif /* FEAT_CMDL_COMPL */
9910
9911/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009912 * Return TRUE if autocmd is supported.
9913 */
9914 int
9915autocmd_supported(name)
9916 char_u *name;
9917{
9918 char_u *p;
9919
9920 return (event_name2nr(name, &p) != NUM_EVENTS);
9921}
9922
9923/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00009924 * Return TRUE if an autocommand is defined for a group, event and
9925 * pattern: The group can be omitted to accept any group. "event" and "pattern"
9926 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
9927 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
9928 * Used for:
9929 * exists("#Group") or
9930 * exists("#Group#Event") or
9931 * exists("#Group#Event#pat") or
9932 * exists("#Event") or
9933 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00009934 */
9935 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00009936au_exists(arg)
9937 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009938{
Bram Moolenaar195d6352005-12-19 22:08:24 +00009939 char_u *arg_save;
9940 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009941 char_u *event_name;
9942 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00009943 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009944 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009945 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00009946 int group;
9947 int retval = FALSE;
9948
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009949 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009950 arg_save = vim_strsave(arg);
9951 if (arg_save == NULL)
9952 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009953 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00009954 if (p != NULL)
9955 *p++ = NUL;
9956
9957 /* First, look for an autocmd group name */
9958 group = au_find_group(arg_save);
9959 if (group == AUGROUP_ERROR)
9960 {
9961 /* Didn't match a group name, assume the first argument is an event. */
9962 group = AUGROUP_ALL;
9963 event_name = arg_save;
9964 }
9965 else
9966 {
9967 if (p == NULL)
9968 {
9969 /* "Group": group name is present and it's recognized */
9970 retval = TRUE;
9971 goto theend;
9972 }
9973
9974 /* Must be "Group#Event" or "Group#Event#pat". */
9975 event_name = p;
9976 p = vim_strchr(event_name, '#');
9977 if (p != NULL)
9978 *p++ = NUL; /* "Group#Event#pat" */
9979 }
9980
9981 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009982
9983 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009984 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009985
9986 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009987 if (event == NUM_EVENTS)
9988 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009989
9990 /* Find the first autocommand for this event.
9991 * If there isn't any, return FALSE;
9992 * If there is one and no pattern given, return TRUE; */
9993 ap = first_autopat[(int)event];
9994 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009995 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009996
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009997 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9998 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009999 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010000 buflocal_buf = curbuf;
10001
Bram Moolenaar071d4272004-06-13 20:20:40 +000010002 /* Check if there is an autocommand with the given pattern. */
10003 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010004 /* only use a pattern when it has not been removed and has commands. */
10005 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010006 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +000010007 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +000010008 && (pattern == NULL
10009 || (buflocal_buf == NULL
10010 ? fnamecmp(ap->pat, pattern) == 0
10011 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +000010012 {
10013 retval = TRUE;
10014 break;
10015 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010016
Bram Moolenaar195d6352005-12-19 22:08:24 +000010017theend:
10018 vim_free(arg_save);
10019 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010020}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010021
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010022#else /* FEAT_AUTOCMD */
10023
10024/*
10025 * Prepare for executing commands for (hidden) buffer "buf".
10026 * This is the non-autocommand version, it simply saves "curbuf" and sets
10027 * "curbuf" and "curwin" to match "buf".
10028 */
10029 void
10030aucmd_prepbuf(aco, buf)
10031 aco_save_T *aco; /* structure to save values in */
10032 buf_T *buf; /* new curbuf */
10033{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010034 aco->save_curbuf = curbuf;
10035 --curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010036 curbuf = buf;
10037 curwin->w_buffer = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010038 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010039}
10040
10041/*
10042 * Restore after executing commands for a (hidden) buffer.
10043 * This is the non-autocommand version.
10044 */
10045 void
10046aucmd_restbuf(aco)
10047 aco_save_T *aco; /* structure holding saved values */
10048{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010049 --curbuf->b_nwindows;
10050 curbuf = aco->save_curbuf;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010051 curwin->w_buffer = curbuf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010052 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010053}
10054
Bram Moolenaar071d4272004-06-13 20:20:40 +000010055#endif /* FEAT_AUTOCMD */
10056
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010057
Bram Moolenaar071d4272004-06-13 20:20:40 +000010058#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
10059/*
Bram Moolenaar748bf032005-02-02 23:04:36 +000010060 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
10061 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
10062 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010063 * Used for autocommands and 'wildignore'.
10064 * Returns TRUE if there is a match, FALSE otherwise.
10065 */
10066 int
Bram Moolenaar748bf032005-02-02 23:04:36 +000010067match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010068 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +000010069 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010070 char_u *fname; /* full path of file name */
10071 char_u *sfname; /* short file name or NULL */
10072 char_u *tail; /* tail of path */
10073 int allow_dirs; /* allow matching with dir */
10074{
10075 regmatch_T regmatch;
10076 int result = FALSE;
10077#ifdef FEAT_OSFILETYPE
10078 int no_pattern = FALSE; /* TRUE if check is filetype only */
10079 char_u *type_start;
10080 char_u c;
10081 int match = FALSE;
10082#endif
10083
Bram Moolenaar71afbfe2013-03-19 16:49:16 +010010084 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010085#ifdef FEAT_OSFILETYPE
10086 if (*pattern == '<')
10087 {
10088 /* There is a filetype condition specified with this pattern.
10089 * Check the filetype matches first. If not, don't bother with the
10090 * pattern (set regprog to NULL).
10091 * Always use magic for the regexp.
10092 */
10093
10094 for (type_start = pattern + 1; (c = *pattern); pattern++)
10095 {
10096 if ((c == ';' || c == '>') && match == FALSE)
10097 {
10098 *pattern = NUL; /* Terminate the string */
Bram Moolenaar05334432011-07-20 18:29:39 +020010099 /* TODO: match with 'filetype' of buffer that "fname" comes
10100 * from. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010101 match = mch_check_filetype(fname, type_start);
10102 *pattern = c; /* Restore the terminator */
10103 type_start = pattern + 1;
10104 }
10105 if (c == '>')
10106 break;
10107 }
10108
10109 /* (c should never be NUL, but check anyway) */
10110 if (match == FALSE || c == NUL)
10111 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
10112 else if (*pattern == NUL)
10113 {
10114 regmatch.regprog = NULL; /* Vim will try to free regprog later */
10115 no_pattern = TRUE; /* Always matches - don't check pat. */
10116 }
10117 else
10118 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
10119 }
10120 else
10121#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +000010122 {
10123 if (prog != NULL)
10124 regmatch.regprog = prog;
10125 else
10126 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
10127 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010128
10129 /*
10130 * Try for a match with the pattern with:
10131 * 1. the full file name, when the pattern has a '/'.
10132 * 2. the short file name, when the pattern has a '/'.
10133 * 3. the tail of the file name, when the pattern has no '/'.
10134 */
10135 if (
10136#ifdef FEAT_OSFILETYPE
10137 /* If the check is for a filetype only and we don't care
10138 * about the path then skip all the regexp stuff.
10139 */
10140 no_pattern ||
10141#endif
10142 (regmatch.regprog != NULL
10143 && ((allow_dirs
10144 && (vim_regexec(&regmatch, fname, (colnr_T)0)
10145 || (sfname != NULL
10146 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
10147 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
10148 result = TRUE;
10149
Bram Moolenaar748bf032005-02-02 23:04:36 +000010150 if (prog == NULL)
Bram Moolenaar473de612013-06-08 18:19:48 +020010151 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010152 return result;
10153}
10154#endif
10155
10156#if defined(FEAT_WILDIGN) || defined(PROTO)
10157/*
10158 * Return TRUE if a file matches with a pattern in "list".
10159 * "list" is a comma-separated list of patterns, like 'wildignore'.
10160 * "sfname" is the short file name or NULL, "ffname" the long file name.
10161 */
10162 int
10163match_file_list(list, sfname, ffname)
10164 char_u *list;
10165 char_u *sfname;
10166 char_u *ffname;
10167{
10168 char_u buf[100];
10169 char_u *tail;
10170 char_u *regpat;
10171 char allow_dirs;
10172 int match;
10173 char_u *p;
10174
10175 tail = gettail(sfname);
10176
10177 /* try all patterns in 'wildignore' */
10178 p = list;
10179 while (*p)
10180 {
10181 copy_option_part(&p, buf, 100, ",");
10182 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
10183 if (regpat == NULL)
10184 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +000010185 match = match_file_pat(regpat, NULL, ffname, sfname,
10186 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010187 vim_free(regpat);
10188 if (match)
10189 return TRUE;
10190 }
10191 return FALSE;
10192}
10193#endif
10194
10195/*
10196 * Convert the given pattern "pat" which has shell style wildcards in it, into
10197 * a regular expression, and return the result in allocated memory. If there
10198 * is a directory path separator to be matched, then TRUE is put in
10199 * allow_dirs, otherwise FALSE is put there -- webb.
10200 * Handle backslashes before special characters, like "\*" and "\ ".
10201 *
10202 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
10203 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
10204 *
10205 * Returns NULL when out of memory.
10206 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010207 char_u *
10208file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
10209 char_u *pat;
10210 char_u *pat_end; /* first char after pattern or NULL */
10211 char *allow_dirs; /* Result passed back out in here */
Bram Moolenaar78a15312009-05-15 19:33:18 +000010212 int no_bslash UNUSED; /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010213{
10214 int size;
10215 char_u *endp;
10216 char_u *reg_pat;
10217 char_u *p;
10218 int i;
10219 int nested = 0;
10220 int add_dollar = TRUE;
10221#ifdef FEAT_OSFILETYPE
10222 int check_length = 0;
10223#endif
10224
10225 if (allow_dirs != NULL)
10226 *allow_dirs = FALSE;
10227 if (pat_end == NULL)
10228 pat_end = pat + STRLEN(pat);
10229
10230#ifdef FEAT_OSFILETYPE
10231 /* Find out how much of the string is the filetype check */
10232 if (*pat == '<')
10233 {
10234 /* Count chars until the next '>' */
10235 for (p = pat + 1; p < pat_end && *p != '>'; p++)
10236 ;
10237 if (p < pat_end)
10238 {
10239 /* Pattern is of the form <.*>.* */
10240 check_length = p - pat + 1;
10241 if (p + 1 >= pat_end)
10242 {
10243 /* The 'pattern' is a filetype check ONLY */
10244 reg_pat = (char_u *)alloc(check_length + 1);
10245 if (reg_pat != NULL)
10246 {
10247 mch_memmove(reg_pat, pat, (size_t)check_length);
10248 reg_pat[check_length] = NUL;
10249 }
10250 return reg_pat;
10251 }
10252 }
10253 /* else: there was no closing '>' - assume it was a normal pattern */
10254
10255 }
10256 pat += check_length;
10257 size = 2 + check_length;
10258#else
10259 size = 2; /* '^' at start, '$' at end */
10260#endif
10261
10262 for (p = pat; p < pat_end; p++)
10263 {
10264 switch (*p)
10265 {
10266 case '*':
10267 case '.':
10268 case ',':
10269 case '{':
10270 case '}':
10271 case '~':
10272 size += 2; /* extra backslash */
10273 break;
10274#ifdef BACKSLASH_IN_FILENAME
10275 case '\\':
10276 case '/':
10277 size += 4; /* could become "[\/]" */
10278 break;
10279#endif
10280 default:
10281 size++;
10282# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010283 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010284 {
10285 ++p;
10286 ++size;
10287 }
10288# endif
10289 break;
10290 }
10291 }
10292 reg_pat = alloc(size + 1);
10293 if (reg_pat == NULL)
10294 return NULL;
10295
10296#ifdef FEAT_OSFILETYPE
10297 /* Copy the type check in to the start. */
10298 if (check_length)
10299 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
10300 i = check_length;
10301#else
10302 i = 0;
10303#endif
10304
10305 if (pat[0] == '*')
10306 while (pat[0] == '*' && pat < pat_end - 1)
10307 pat++;
10308 else
10309 reg_pat[i++] = '^';
10310 endp = pat_end - 1;
10311 if (*endp == '*')
10312 {
10313 while (endp - pat > 0 && *endp == '*')
10314 endp--;
10315 add_dollar = FALSE;
10316 }
10317 for (p = pat; *p && nested >= 0 && p <= endp; p++)
10318 {
10319 switch (*p)
10320 {
10321 case '*':
10322 reg_pat[i++] = '.';
10323 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +000010324 while (p[1] == '*') /* "**" matches like "*" */
10325 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010326 break;
10327 case '.':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010328 case '~':
10329 reg_pat[i++] = '\\';
10330 reg_pat[i++] = *p;
10331 break;
10332 case '?':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010333 reg_pat[i++] = '.';
10334 break;
10335 case '\\':
10336 if (p[1] == NUL)
10337 break;
10338#ifdef BACKSLASH_IN_FILENAME
10339 if (!no_bslash)
10340 {
10341 /* translate:
10342 * "\x" to "\\x" e.g., "dir\file"
10343 * "\*" to "\\.*" e.g., "dir\*.c"
10344 * "\?" to "\\." e.g., "dir\??.c"
10345 * "\+" to "\+" e.g., "fileX\+.c"
10346 */
10347 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
10348 && p[1] != '+')
10349 {
10350 reg_pat[i++] = '[';
10351 reg_pat[i++] = '\\';
10352 reg_pat[i++] = '/';
10353 reg_pat[i++] = ']';
10354 if (allow_dirs != NULL)
10355 *allow_dirs = TRUE;
10356 break;
10357 }
10358 }
10359#endif
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010360 /* Undo escaping from ExpandEscape():
10361 * foo\?bar -> foo?bar
10362 * foo\%bar -> foo%bar
10363 * foo\,bar -> foo,bar
10364 * foo\ bar -> foo bar
10365 * Don't unescape \, * and others that are also special in a
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010366 * regexp.
10367 * An escaped { must be unescaped since we use magic not
Bram Moolenaara946afe2013-08-02 15:22:39 +020010368 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010369 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010370 if (*++p == '?'
10371#ifdef BACKSLASH_IN_FILENAME
10372 && no_bslash
10373#endif
10374 )
10375 reg_pat[i++] = '?';
10376 else
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010377 if (*p == ',' || *p == '%' || *p == '#'
Bram Moolenaara946afe2013-08-02 15:22:39 +020010378 || *p == ' ' || *p == '{' || *p == '}')
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010379 reg_pat[i++] = *p;
Bram Moolenaara946afe2013-08-02 15:22:39 +020010380 else if (*p == '\\' && p[1] == '\\' && p[2] == '{')
10381 {
10382 reg_pat[i++] = '\\';
10383 reg_pat[i++] = '{';
10384 p += 2;
10385 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010386 else
10387 {
10388 if (allow_dirs != NULL && vim_ispathsep(*p)
10389#ifdef BACKSLASH_IN_FILENAME
10390 && (!no_bslash || *p != '\\')
10391#endif
10392 )
10393 *allow_dirs = TRUE;
10394 reg_pat[i++] = '\\';
10395 reg_pat[i++] = *p;
10396 }
10397 break;
10398#ifdef BACKSLASH_IN_FILENAME
10399 case '/':
10400 reg_pat[i++] = '[';
10401 reg_pat[i++] = '\\';
10402 reg_pat[i++] = '/';
10403 reg_pat[i++] = ']';
10404 if (allow_dirs != NULL)
10405 *allow_dirs = TRUE;
10406 break;
10407#endif
10408 case '{':
10409 reg_pat[i++] = '\\';
10410 reg_pat[i++] = '(';
10411 nested++;
10412 break;
10413 case '}':
10414 reg_pat[i++] = '\\';
10415 reg_pat[i++] = ')';
10416 --nested;
10417 break;
10418 case ',':
10419 if (nested)
10420 {
10421 reg_pat[i++] = '\\';
10422 reg_pat[i++] = '|';
10423 }
10424 else
10425 reg_pat[i++] = ',';
10426 break;
10427 default:
10428# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010429 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010430 reg_pat[i++] = *p++;
10431 else
10432# endif
10433 if (allow_dirs != NULL && vim_ispathsep(*p))
10434 *allow_dirs = TRUE;
10435 reg_pat[i++] = *p;
10436 break;
10437 }
10438 }
10439 if (add_dollar)
10440 reg_pat[i++] = '$';
10441 reg_pat[i] = NUL;
10442 if (nested != 0)
10443 {
10444 if (nested < 0)
10445 EMSG(_("E219: Missing {."));
10446 else
10447 EMSG(_("E220: Missing }."));
10448 vim_free(reg_pat);
10449 reg_pat = NULL;
10450 }
10451 return reg_pat;
10452}
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010453
10454#if defined(EINTR) || defined(PROTO)
10455/*
10456 * Version of read() that retries when interrupted by EINTR (possibly
10457 * by a SIGWINCH).
10458 */
10459 long
10460read_eintr(fd, buf, bufsize)
10461 int fd;
10462 void *buf;
10463 size_t bufsize;
10464{
10465 long ret;
10466
10467 for (;;)
10468 {
10469 ret = vim_read(fd, buf, bufsize);
10470 if (ret >= 0 || errno != EINTR)
10471 break;
10472 }
10473 return ret;
10474}
10475
10476/*
10477 * Version of write() that retries when interrupted by EINTR (possibly
10478 * by a SIGWINCH).
10479 */
10480 long
10481write_eintr(fd, buf, bufsize)
10482 int fd;
10483 void *buf;
10484 size_t bufsize;
10485{
10486 long ret = 0;
10487 long wlen;
10488
10489 /* Repeat the write() so long it didn't fail, other than being interrupted
10490 * by a signal. */
10491 while (ret < (long)bufsize)
10492 {
Bram Moolenaar9c263032010-12-17 18:06:06 +010010493 wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010494 if (wlen < 0)
10495 {
10496 if (errno != EINTR)
10497 break;
10498 }
10499 else
10500 ret += wlen;
10501 }
10502 return ret;
10503}
10504#endif