blob: 233990bf502418ca155c0f23270b3329f2f1e455 [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 */
1188#if SIZEOF_INT <= 2
1189 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 {
1200#if 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);
2976 bf_ofb_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);
3028 bf_ofb_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);
3067 bf_ofb_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 Moolenaar588ebeb2008-05-07 17:09:24 +00004033# ifdef HAVE_SELINUX
4034 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 Moolenaar588ebeb2008-05-07 17:09:24 +00004072#ifdef HAVE_SELINUX
4073 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 Moolenaar588ebeb2008-05-07 17:09:24 +00004721#ifdef HAVE_SELINUX
4722 /* 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 Moolenaarf9b01292010-06-12 06:45:20 +02005297 "%ldL, %lldC", lnum, 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 Moolenaarf9b01292010-06-12 06:45:20 +02005315 _("%lld characters"), 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 Moolenaar071d4272004-06-13 20:20:40 +00006710 if (errmsg != NULL)
6711 {
6712 EMSG2(errmsg, to);
6713 return -1;
6714 }
6715 mch_remove(from);
6716 return 0;
6717}
6718
6719static int already_warned = FALSE;
6720
6721/*
6722 * Check if any not hidden buffer has been changed.
6723 * Postpone the check if there are characters in the stuff buffer, a global
6724 * command is being executed, a mapping is being executed or an autocommand is
6725 * busy.
6726 * Returns TRUE if some message was written (screen should be redrawn and
6727 * cursor positioned).
6728 */
6729 int
6730check_timestamps(focus)
6731 int focus; /* called for GUI focus event */
6732{
6733 buf_T *buf;
6734 int didit = 0;
6735 int n;
6736
6737 /* Don't check timestamps while system() or another low-level function may
6738 * cause us to lose and gain focus. */
6739 if (no_check_timestamps > 0)
6740 return FALSE;
6741
6742 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6743 * event and we would keep on checking if the file is steadily growing.
6744 * Do check again after typing something. */
6745 if (focus && did_check_timestamps)
6746 {
6747 need_check_timestamps = TRUE;
6748 return FALSE;
6749 }
6750
6751 if (!stuff_empty() || global_busy || !typebuf_typed()
6752#ifdef FEAT_AUTOCMD
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006753 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006754#endif
6755 )
6756 need_check_timestamps = TRUE; /* check later */
6757 else
6758 {
6759 ++no_wait_return;
6760 did_check_timestamps = TRUE;
6761 already_warned = FALSE;
6762 for (buf = firstbuf; buf != NULL; )
6763 {
6764 /* Only check buffers in a window. */
6765 if (buf->b_nwindows > 0)
6766 {
6767 n = buf_check_timestamp(buf, focus);
6768 if (didit < n)
6769 didit = n;
6770 if (n > 0 && !buf_valid(buf))
6771 {
6772 /* Autocommands have removed the buffer, start at the
6773 * first one again. */
6774 buf = firstbuf;
6775 continue;
6776 }
6777 }
6778 buf = buf->b_next;
6779 }
6780 --no_wait_return;
6781 need_check_timestamps = FALSE;
6782 if (need_wait_return && didit == 2)
6783 {
6784 /* make sure msg isn't overwritten */
6785 msg_puts((char_u *)"\n");
6786 out_flush();
6787 }
6788 }
6789 return didit;
6790}
6791
6792/*
6793 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6794 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6795 * empty.
6796 */
6797 static int
6798move_lines(frombuf, tobuf)
6799 buf_T *frombuf;
6800 buf_T *tobuf;
6801{
6802 buf_T *tbuf = curbuf;
6803 int retval = OK;
6804 linenr_T lnum;
6805 char_u *p;
6806
6807 /* Copy the lines in "frombuf" to "tobuf". */
6808 curbuf = tobuf;
6809 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6810 {
6811 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6812 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6813 {
6814 vim_free(p);
6815 retval = FAIL;
6816 break;
6817 }
6818 vim_free(p);
6819 }
6820
6821 /* Delete all the lines in "frombuf". */
6822 if (retval != FAIL)
6823 {
6824 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006825 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6826 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006827 {
6828 /* Oops! We could try putting back the saved lines, but that
6829 * might fail again... */
6830 retval = FAIL;
6831 break;
6832 }
6833 }
6834
6835 curbuf = tbuf;
6836 return retval;
6837}
6838
6839/*
6840 * Check if buffer "buf" has been changed.
6841 * Also check if the file for a new buffer unexpectedly appeared.
6842 * return 1 if a changed buffer was found.
6843 * return 2 if a message has been displayed.
6844 * return 0 otherwise.
6845 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006846 int
6847buf_check_timestamp(buf, focus)
6848 buf_T *buf;
Bram Moolenaar78a15312009-05-15 19:33:18 +00006849 int focus UNUSED; /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006850{
6851 struct stat st;
6852 int stat_res;
6853 int retval = 0;
6854 char_u *path;
6855 char_u *tbuf;
6856 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006857 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006858 int helpmesg = FALSE;
6859 int reload = FALSE;
6860#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6861 int can_reload = FALSE;
6862#endif
Bram Moolenaar914703b2010-05-31 21:59:46 +02006863 off_t orig_size = buf->b_orig_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006864 int orig_mode = buf->b_orig_mode;
6865#ifdef FEAT_GUI
6866 int save_mouse_correct = need_mouse_correct;
6867#endif
6868#ifdef FEAT_AUTOCMD
6869 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006870 int n;
6871 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006872#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006873 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006874
6875 /* If there is no file name, the buffer is not loaded, 'buftype' is
6876 * set, we are in the middle of a save or being called recursively: ignore
6877 * this buffer. */
6878 if (buf->b_ffname == NULL
6879 || buf->b_ml.ml_mfp == NULL
6880#if defined(FEAT_QUICKFIX)
6881 || *buf->b_p_bt != NUL
6882#endif
6883 || buf->b_saving
6884#ifdef FEAT_AUTOCMD
6885 || busy
6886#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006887#ifdef FEAT_NETBEANS_INTG
6888 || isNetbeansBuffer(buf)
6889#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006890 )
6891 return 0;
6892
6893 if ( !(buf->b_flags & BF_NOTEDITED)
6894 && buf->b_mtime != 0
6895 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6896 || time_differs((long)st.st_mtime, buf->b_mtime)
6897#ifdef HAVE_ST_MODE
6898 || (int)st.st_mode != buf->b_orig_mode
6899#else
6900 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6901#endif
6902 ))
6903 {
6904 retval = 1;
6905
Bram Moolenaar316059c2006-01-14 21:18:42 +00006906 /* set b_mtime to stop further warnings (e.g., when executing
6907 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006908 if (stat_res < 0)
6909 {
6910 buf->b_mtime = 0;
6911 buf->b_orig_size = 0;
6912 buf->b_orig_mode = 0;
6913 }
6914 else
6915 buf_store_time(buf, &st, buf->b_ffname);
6916
6917 /* Don't do anything for a directory. Might contain the file
6918 * explorer. */
6919 if (mch_isdir(buf->b_fname))
6920 ;
6921
6922 /*
6923 * If 'autoread' is set, the buffer has no changes and the file still
6924 * exists, reload the buffer. Use the buffer-local option value if it
6925 * was set, the global option value otherwise.
6926 */
6927 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6928 && !bufIsChanged(buf) && stat_res >= 0)
6929 reload = TRUE;
6930 else
6931 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006932 if (stat_res < 0)
6933 reason = "deleted";
6934 else if (bufIsChanged(buf))
6935 reason = "conflict";
6936 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6937 reason = "changed";
6938 else if (orig_mode != buf->b_orig_mode)
6939 reason = "mode";
6940 else
6941 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006942
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006943#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006944 /*
6945 * Only give the warning if there are no FileChangedShell
6946 * autocommands.
6947 * Avoid being called recursively by setting "busy".
6948 */
6949 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006950# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006951 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6952 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006953# endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006954 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006955 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6956 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006957 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006958 busy = FALSE;
6959 if (n)
6960 {
6961 if (!buf_valid(buf))
6962 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006963# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006964 s = get_vim_var_str(VV_FCS_CHOICE);
6965 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6966 reload = TRUE;
6967 else if (STRCMP(s, "ask") == 0)
6968 n = FALSE;
6969 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006970# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006971 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006972 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006973 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006974#endif
6975 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006976 if (*reason == 'd')
6977 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006978 else
6979 {
6980 helpmesg = TRUE;
6981#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6982 can_reload = TRUE;
6983#endif
6984 /*
6985 * Check if the file contents really changed to avoid
6986 * giving a warning when only the timestamp was set (e.g.,
6987 * checked out of CVS). Always warn when the buffer was
6988 * changed.
6989 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006990 if (reason[2] == 'n')
6991 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006992 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006993 mesg2 = _("See \":help W12\" for more info.");
6994 }
6995 else if (reason[1] == 'h')
6996 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006997 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006998 mesg2 = _("See \":help W11\" for more info.");
6999 }
7000 else if (*reason == 'm')
7001 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007002 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007003 mesg2 = _("See \":help W16\" for more info.");
7004 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00007005 else
7006 /* Only timestamp changed, store it to avoid a warning
7007 * in check_mtime() later. */
7008 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007009 }
7010 }
7011 }
7012
7013 }
7014 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
7015 && vim_fexists(buf->b_ffname))
7016 {
7017 retval = 1;
7018 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
7019 buf->b_flags |= BF_NEW_W;
7020#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7021 can_reload = TRUE;
7022#endif
7023 }
7024
7025 if (mesg != NULL)
7026 {
7027 path = home_replace_save(buf, buf->b_fname);
7028 if (path != NULL)
7029 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007030 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007031 mesg2 = "";
7032 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
7033 + STRLEN(mesg2) + 2));
7034 sprintf((char *)tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00007035#ifdef FEAT_EVAL
7036 /* Set warningmsg here, before the unimportant and output-specific
7037 * mesg2 has been appended. */
7038 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
7039#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007040#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
7041 if (can_reload)
7042 {
7043 if (*mesg2 != NUL)
7044 {
7045 STRCAT(tbuf, "\n");
7046 STRCAT(tbuf, mesg2);
7047 }
7048 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01007049 (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007050 reload = TRUE;
7051 }
7052 else
7053#endif
7054 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
7055 {
7056 if (*mesg2 != NUL)
7057 {
7058 STRCAT(tbuf, "; ");
7059 STRCAT(tbuf, mesg2);
7060 }
7061 EMSG(tbuf);
7062 retval = 2;
7063 }
7064 else
7065 {
Bram Moolenaared203462004-06-16 11:19:22 +00007066# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00007067 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00007068# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007069 {
7070 msg_start();
7071 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
7072 if (*mesg2 != NUL)
7073 msg_puts_attr((char_u *)mesg2,
7074 hl_attr(HLF_W) + MSG_HIST);
7075 msg_clr_eos();
7076 (void)msg_end();
7077 if (emsg_silent == 0)
7078 {
7079 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00007080# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00007081 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00007082# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007083 /* give the user some time to think about it */
7084 ui_delay(1000L, TRUE);
7085
7086 /* don't redraw and erase the message */
7087 redraw_cmdline = FALSE;
7088 }
7089 }
7090 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007091 }
7092
7093 vim_free(path);
7094 vim_free(tbuf);
7095 }
7096 }
7097
7098 if (reload)
Bram Moolenaar465748e2012-08-29 18:50:54 +02007099 {
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007100 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00007101 buf_reload(buf, orig_mode);
Bram Moolenaar465748e2012-08-29 18:50:54 +02007102#ifdef FEAT_PERSISTENT_UNDO
7103 if (buf->b_p_udf && buf->b_ffname != NULL)
7104 {
7105 char_u hash[UNDO_HASH_SIZE];
7106 buf_T *save_curbuf = curbuf;
7107
7108 /* Any existing undo file is unusable, write it now. */
7109 curbuf = buf;
7110 u_compute_hash(hash);
7111 u_write_undo(NULL, FALSE, buf, hash);
7112 curbuf = save_curbuf;
7113 }
7114#endif
7115 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007116
Bram Moolenaar56718732006-03-15 22:53:57 +00007117#ifdef FEAT_AUTOCMD
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00007118 /* Trigger FileChangedShell when the file was changed in any way. */
7119 if (buf_valid(buf) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00007120 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
7121 buf->b_fname, buf->b_fname, FALSE, buf);
7122#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007123#ifdef FEAT_GUI
7124 /* restore this in case an autocommand has set it; it would break
7125 * 'mousefocus' */
7126 need_mouse_correct = save_mouse_correct;
7127#endif
7128
7129 return retval;
7130}
7131
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007132/*
7133 * Reload a buffer that is already loaded.
7134 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00007135 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
7136 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007137 */
7138 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00007139buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007140 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00007141 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007142{
7143 exarg_T ea;
7144 pos_T old_cursor;
7145 linenr_T old_topline;
7146 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007147 buf_T *savebuf;
7148 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007149 aco_save_T aco;
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007150 int flags = READ_NEW;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007151
7152 /* set curwin/curbuf for "buf" and save some things */
7153 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007154
7155 /* We only want to read the text from the file, not reset the syntax
7156 * highlighting, clear marks, diff status, etc. Force the fileformat
7157 * and encoding to be the same. */
7158 if (prep_exarg(&ea, buf) == OK)
7159 {
7160 old_cursor = curwin->w_cursor;
7161 old_topline = curwin->w_topline;
7162
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007163 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007164 {
7165 /* Save all the text, so that the reload can be undone.
7166 * Sync first so that this is a separate undo-able action. */
7167 u_sync(FALSE);
7168 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
7169 flags |= READ_KEEP_UNDO;
7170 }
7171
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007172 /*
7173 * To behave like when a new file is edited (matters for
7174 * BufReadPost autocommands) we first need to delete the current
7175 * buffer contents. But if reading the file fails we should keep
7176 * the old contents. Can't use memory only, the file might be
7177 * too big. Use a hidden buffer to move the buffer contents to.
7178 */
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007179 if (bufempty() || saved == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007180 savebuf = NULL;
7181 else
7182 {
7183 /* Allocate a buffer without putting it in the buffer list. */
7184 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007185 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007186 {
7187 /* Open the memline. */
7188 curbuf = savebuf;
7189 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00007190 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007191 curbuf = buf;
7192 curwin->w_buffer = buf;
7193 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00007194 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007195 || move_lines(buf, savebuf) == FAIL)
7196 {
7197 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
7198 buf->b_fname);
7199 saved = FAIL;
7200 }
7201 }
7202
7203 if (saved == OK)
7204 {
7205 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
7206#ifdef FEAT_AUTOCMD
7207 keep_filetype = TRUE; /* don't detect 'filetype' */
7208#endif
7209 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
7210 (linenr_T)0,
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007211 (linenr_T)MAXLNUM, &ea, flags) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007212 {
7213#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
7214 if (!aborting())
7215#endif
7216 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar8424a622006-04-19 21:23:36 +00007217 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007218 {
7219 /* Put the text back from the save buffer. First
7220 * delete any lines that readfile() added. */
7221 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00007222 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007223 break;
7224 (void)move_lines(savebuf, buf);
7225 }
7226 }
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007227 else if (buf == curbuf) /* "buf" still valid */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007228 {
7229 /* Mark the buffer as unmodified and free undo info. */
7230 unchanged(buf, TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007231 if ((flags & READ_KEEP_UNDO) == 0)
7232 {
7233 u_blockfree(buf);
7234 u_clearall(buf);
7235 }
7236 else
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007237 {
Bram Moolenaar59f931e2010-07-24 20:27:03 +02007238 /* Mark all undo states as changed. */
7239 u_unchanged(curbuf);
Bram Moolenaarf9bb7342010-08-04 14:29:54 +02007240 }
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007241 }
7242 }
7243 vim_free(ea.cmd);
7244
Bram Moolenaar8424a622006-04-19 21:23:36 +00007245 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007246 wipe_buffer(savebuf, FALSE);
7247
7248#ifdef FEAT_DIFF
7249 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00007250 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007251#endif
7252
7253 /* Restore the topline and cursor position and check it (lines may
7254 * have been removed). */
7255 if (old_topline > curbuf->b_ml.ml_line_count)
7256 curwin->w_topline = curbuf->b_ml.ml_line_count;
7257 else
7258 curwin->w_topline = old_topline;
7259 curwin->w_cursor = old_cursor;
7260 check_cursor();
7261 update_topline();
7262#ifdef FEAT_AUTOCMD
7263 keep_filetype = FALSE;
7264#endif
7265#ifdef FEAT_FOLDING
7266 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007267 win_T *wp;
7268 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007269
7270 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007271 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007272 if (wp->w_buffer == curwin->w_buffer
7273 && !foldmethodIsManual(wp))
7274 foldUpdateAll(wp);
7275 }
7276#endif
7277 /* If the mode didn't change and 'readonly' was set, keep the old
7278 * value; the user probably used the ":view" command. But don't
7279 * reset it, might have had a read error. */
7280 if (orig_mode == curbuf->b_orig_mode)
7281 curbuf->b_p_ro |= old_ro;
Bram Moolenaar52f85b72013-01-30 14:13:56 +01007282
7283 /* Modelines must override settings done by autocommands. */
7284 do_modelines(0);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007285 }
7286
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007287 /* restore curwin/curbuf and a few other things */
7288 aucmd_restbuf(&aco);
7289 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007290}
7291
Bram Moolenaar071d4272004-06-13 20:20:40 +00007292 void
7293buf_store_time(buf, st, fname)
7294 buf_T *buf;
7295 struct stat *st;
Bram Moolenaar78a15312009-05-15 19:33:18 +00007296 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007297{
7298 buf->b_mtime = (long)st->st_mtime;
Bram Moolenaar914703b2010-05-31 21:59:46 +02007299 buf->b_orig_size = st->st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007300#ifdef HAVE_ST_MODE
7301 buf->b_orig_mode = (int)st->st_mode;
7302#else
7303 buf->b_orig_mode = mch_getperm(fname);
7304#endif
7305}
7306
7307/*
7308 * Adjust the line with missing eol, used for the next write.
7309 * Used for do_filter(), when the input lines for the filter are deleted.
7310 */
7311 void
7312write_lnum_adjust(offset)
7313 linenr_T offset;
7314{
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01007315 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
7316 curbuf->b_no_eol_lnum += offset;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007317}
7318
7319#if defined(TEMPDIRNAMES) || defined(PROTO)
7320static long temp_count = 0; /* Temp filename counter. */
7321
7322/*
7323 * Delete the temp directory and all files it contains.
7324 */
7325 void
7326vim_deltempdir()
7327{
7328 char_u **files;
7329 int file_count;
7330 int i;
7331
7332 if (vim_tempdir != NULL)
7333 {
7334 sprintf((char *)NameBuff, "%s*", vim_tempdir);
7335 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
7336 EW_DIR|EW_FILE|EW_SILENT) == OK)
7337 {
7338 for (i = 0; i < file_count; ++i)
7339 mch_remove(files[i]);
7340 FreeWild(file_count, files);
7341 }
7342 gettail(NameBuff)[-1] = NUL;
7343 (void)mch_rmdir(NameBuff);
7344
7345 vim_free(vim_tempdir);
7346 vim_tempdir = NULL;
7347 }
7348}
7349#endif
7350
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007351#ifdef TEMPDIRNAMES
Bram Moolenaar071d4272004-06-13 20:20:40 +00007352/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007353 * Directory "tempdir" was created. Expand this name to a full path and put
7354 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7355 * "tempdir" must be no longer than MAXPATHL.
7356 */
7357 static void
7358vim_settempdir(tempdir)
7359 char_u *tempdir;
7360{
7361 char_u *buf;
7362
7363 buf = alloc((unsigned)MAXPATHL + 2);
7364 if (buf != NULL)
7365 {
7366 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7367 STRCPY(buf, tempdir);
7368# ifdef __EMX__
7369 if (vim_strchr(buf, '/') != NULL)
7370 STRCAT(buf, "/");
7371 else
7372# endif
7373 add_pathsep(buf);
7374 vim_tempdir = vim_strsave(buf);
7375 vim_free(buf);
7376 }
7377}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007378#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007379
7380/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007381 * vim_tempname(): Return a unique name that can be used for a temp file.
7382 *
7383 * The temp file is NOT created.
7384 *
7385 * The returned pointer is to allocated memory.
7386 * The returned pointer is NULL if no valid name was found.
7387 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007388 char_u *
7389vim_tempname(extra_char)
Bram Moolenaar78a15312009-05-15 19:33:18 +00007390 int extra_char UNUSED; /* char to use in the name instead of '?' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007391{
7392#ifdef USE_TMPNAM
7393 char_u itmp[L_tmpnam]; /* use tmpnam() */
7394#else
7395 char_u itmp[TEMPNAMELEN];
7396#endif
7397
7398#ifdef TEMPDIRNAMES
7399 static char *(tempdirs[]) = {TEMPDIRNAMES};
7400 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007401# ifndef EEXIST
7402 struct stat st;
7403# endif
7404
7405 /*
7406 * This will create a directory for private use by this instance of Vim.
7407 * This is done once, and the same directory is used for all temp files.
7408 * This method avoids security problems because of symlink attacks et al.
7409 * It's also a bit faster, because we only need to check for an existing
7410 * file when creating the directory and not for each temp file.
7411 */
7412 if (vim_tempdir == NULL)
7413 {
7414 /*
7415 * Try the entries in TEMPDIRNAMES to create the temp directory.
7416 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007417 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007418 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007419# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007420 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007421 long nr;
7422 long off;
7423# endif
7424
Bram Moolenaar071d4272004-06-13 20:20:40 +00007425 /* expand $TMP, leave room for "/v1100000/999999999" */
7426 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
7427 if (mch_isdir(itmp)) /* directory exists */
7428 {
7429# ifdef __EMX__
7430 /* If $TMP contains a forward slash (perhaps using bash or
7431 * tcsh), don't add a backslash, use a forward slash!
7432 * Adding 2 backslashes didn't work. */
7433 if (vim_strchr(itmp, '/') != NULL)
7434 STRCAT(itmp, "/");
7435 else
7436# endif
7437 add_pathsep(itmp);
7438
Bram Moolenaareaf03392009-11-17 11:08:52 +00007439# ifdef HAVE_MKDTEMP
7440 /* Leave room for filename */
7441 STRCAT(itmp, "vXXXXXX");
7442 if (mkdtemp((char *)itmp) != NULL)
7443 vim_settempdir(itmp);
7444# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007445 /* Get an arbitrary number of up to 6 digits. When it's
7446 * unlikely that it already exists it will be faster,
7447 * otherwise it doesn't matter. The use of mkdir() avoids any
7448 * security problems because of the predictable number. */
7449 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007450 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007451
7452 /* Try up to 10000 different values until we find a name that
7453 * doesn't exist. */
7454 for (off = 0; off < 10000L; ++off)
7455 {
7456 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007457# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007458 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007459# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007460
Bram Moolenaareaf03392009-11-17 11:08:52 +00007461 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7462# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007463 /* If mkdir() does not set errno to EEXIST, check for
7464 * existing file here. There is a race condition then,
7465 * although it's fail-safe. */
7466 if (mch_stat((char *)itmp, &st) >= 0)
7467 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007468# endif
7469# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 /* Make sure the umask doesn't remove the executable bit.
7471 * "repl" has been reported to use "177". */
7472 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007473# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007474 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007475# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007476 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007477# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478 if (r == 0)
7479 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007480 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007481 break;
7482 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007483# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007484 /* If the mkdir() didn't fail because the file/dir exists,
7485 * we probably can't create any dir here, try another
7486 * place. */
7487 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007488# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007489 break;
7490 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007491# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007492 if (vim_tempdir != NULL)
7493 break;
7494 }
7495 }
7496 }
7497
7498 if (vim_tempdir != NULL)
7499 {
7500 /* There is no need to check if the file exists, because we own the
7501 * directory and nobody else creates a file in it. */
7502 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7503 return vim_strsave(itmp);
7504 }
7505
7506 return NULL;
7507
7508#else /* TEMPDIRNAMES */
7509
7510# ifdef WIN3264
7511 char szTempFile[_MAX_PATH + 1];
7512 char buf4[4];
7513 char_u *retval;
7514 char_u *p;
7515
7516 STRCPY(itmp, "");
7517 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
Bram Moolenaarb1891912011-02-09 14:47:03 +01007518 {
7519 szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */
7520 szTempFile[1] = NUL;
7521 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007522 strcpy(buf4, "VIM");
7523 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
7524 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
7525 return NULL;
7526 /* GetTempFileName() will create the file, we don't want that */
7527 (void)DeleteFile(itmp);
7528
7529 /* Backslashes in a temp file name cause problems when filtering with
7530 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7531 * didn't set 'shellslash'. */
7532 retval = vim_strsave(itmp);
7533 if (*p_shcf == '-' || p_ssl)
7534 for (p = retval; *p; ++p)
7535 if (*p == '\\')
7536 *p = '/';
7537 return retval;
7538
7539# else /* WIN3264 */
7540
7541# ifdef USE_TMPNAM
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007542 char_u *p;
7543
Bram Moolenaar071d4272004-06-13 20:20:40 +00007544 /* tmpnam() will make its own name */
Bram Moolenaar95474ca2011-02-09 16:44:51 +01007545 p = tmpnam((char *)itmp);
7546 if (p == NULL || *p == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007547 return NULL;
7548# else
7549 char_u *p;
7550
7551# ifdef VMS_TEMPNAM
7552 /* mktemp() is not working on VMS. It seems to be
7553 * a do-nothing function. Therefore we use tempnam().
7554 */
7555 sprintf((char *)itmp, "VIM%c", extra_char);
7556 p = (char_u *)tempnam("tmp:", (char *)itmp);
7557 if (p != NULL)
7558 {
7559 /* VMS will use '.LOG' if we don't explicitly specify an extension,
7560 * and VIM will then be unable to find the file later */
7561 STRCPY(itmp, p);
7562 STRCAT(itmp, ".txt");
7563 free(p);
7564 }
7565 else
7566 return NULL;
7567# else
7568 STRCPY(itmp, TEMPNAME);
7569 if ((p = vim_strchr(itmp, '?')) != NULL)
7570 *p = extra_char;
7571 if (mktemp((char *)itmp) == NULL)
7572 return NULL;
7573# endif
7574# endif
7575
7576 return vim_strsave(itmp);
7577# endif /* WIN3264 */
7578#endif /* TEMPDIRNAMES */
7579}
7580
7581#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7582/*
7583 * Convert all backslashes in fname to forward slashes in-place.
7584 */
7585 void
7586forward_slash(fname)
7587 char_u *fname;
7588{
7589 char_u *p;
7590
7591 for (p = fname; *p != NUL; ++p)
7592# ifdef FEAT_MBYTE
7593 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007594 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007595 ++p;
7596 else
7597# endif
7598 if (*p == '\\')
7599 *p = '/';
7600}
7601#endif
7602
7603
7604/*
7605 * Code for automatic commands.
7606 *
7607 * Only included when "FEAT_AUTOCMD" has been defined.
7608 */
7609
7610#if defined(FEAT_AUTOCMD) || defined(PROTO)
7611
7612/*
7613 * The autocommands are stored in a list for each event.
7614 * Autocommands for the same pattern, that are consecutive, are joined
7615 * together, to avoid having to match the pattern too often.
7616 * The result is an array of Autopat lists, which point to AutoCmd lists:
7617 *
7618 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7619 * Autopat.cmds Autopat.cmds
7620 * | |
7621 * V V
7622 * AutoCmd.next AutoCmd.next
7623 * | |
7624 * V V
7625 * AutoCmd.next NULL
7626 * |
7627 * V
7628 * NULL
7629 *
7630 * first_autopat[1] --> Autopat.next --> NULL
7631 * Autopat.cmds
7632 * |
7633 * V
7634 * AutoCmd.next
7635 * |
7636 * V
7637 * NULL
7638 * etc.
7639 *
7640 * The order of AutoCmds is important, this is the order in which they were
7641 * defined and will have to be executed.
7642 */
7643typedef struct AutoCmd
7644{
7645 char_u *cmd; /* The command to be executed (NULL
7646 when command has been removed) */
7647 char nested; /* If autocommands nest here */
7648 char last; /* last command in list */
7649#ifdef FEAT_EVAL
7650 scid_T scriptID; /* script ID where defined */
7651#endif
7652 struct AutoCmd *next; /* Next AutoCmd in list */
7653} AutoCmd;
7654
7655typedef struct AutoPat
7656{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007657 char_u *pat; /* pattern as typed (NULL when pattern
7658 has been removed) */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007659 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007660 AutoCmd *cmds; /* list of commands to do */
7661 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007662 int group; /* group ID */
7663 int patlen; /* strlen() of pat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007664 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar6395af82013-06-12 19:52:15 +02007665 char allow_dirs; /* Pattern may match whole path */
7666 char last; /* last pattern for apply_autocmds() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007667} AutoPat;
7668
7669static struct event_name
7670{
7671 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007672 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007673} event_names[] =
7674{
7675 {"BufAdd", EVENT_BUFADD},
7676 {"BufCreate", EVENT_BUFADD},
7677 {"BufDelete", EVENT_BUFDELETE},
7678 {"BufEnter", EVENT_BUFENTER},
7679 {"BufFilePost", EVENT_BUFFILEPOST},
7680 {"BufFilePre", EVENT_BUFFILEPRE},
7681 {"BufHidden", EVENT_BUFHIDDEN},
7682 {"BufLeave", EVENT_BUFLEAVE},
7683 {"BufNew", EVENT_BUFNEW},
7684 {"BufNewFile", EVENT_BUFNEWFILE},
7685 {"BufRead", EVENT_BUFREADPOST},
7686 {"BufReadCmd", EVENT_BUFREADCMD},
7687 {"BufReadPost", EVENT_BUFREADPOST},
7688 {"BufReadPre", EVENT_BUFREADPRE},
7689 {"BufUnload", EVENT_BUFUNLOAD},
7690 {"BufWinEnter", EVENT_BUFWINENTER},
7691 {"BufWinLeave", EVENT_BUFWINLEAVE},
7692 {"BufWipeout", EVENT_BUFWIPEOUT},
7693 {"BufWrite", EVENT_BUFWRITEPRE},
7694 {"BufWritePost", EVENT_BUFWRITEPOST},
7695 {"BufWritePre", EVENT_BUFWRITEPRE},
7696 {"BufWriteCmd", EVENT_BUFWRITECMD},
7697 {"CmdwinEnter", EVENT_CMDWINENTER},
7698 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007699 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaarcfa3cae2012-07-10 17:14:56 +02007700 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007701 {"CursorHold", EVENT_CURSORHOLD},
7702 {"CursorHoldI", EVENT_CURSORHOLDI},
7703 {"CursorMoved", EVENT_CURSORMOVED},
7704 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007705 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7706 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007707 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7708 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7709 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7710 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007711 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007712 {"FileChangedRO", EVENT_FILECHANGEDRO},
7713 {"FileReadPost", EVENT_FILEREADPOST},
7714 {"FileReadPre", EVENT_FILEREADPRE},
7715 {"FileReadCmd", EVENT_FILEREADCMD},
7716 {"FileType", EVENT_FILETYPE},
7717 {"FileWritePost", EVENT_FILEWRITEPOST},
7718 {"FileWritePre", EVENT_FILEWRITEPRE},
7719 {"FileWriteCmd", EVENT_FILEWRITECMD},
7720 {"FilterReadPost", EVENT_FILTERREADPOST},
7721 {"FilterReadPre", EVENT_FILTERREADPRE},
7722 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7723 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7724 {"FocusGained", EVENT_FOCUSGAINED},
7725 {"FocusLost", EVENT_FOCUSLOST},
7726 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7727 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007728 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007729 {"InsertChange", EVENT_INSERTCHANGE},
7730 {"InsertEnter", EVENT_INSERTENTER},
7731 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaare659c952011-05-19 17:25:41 +02007732 {"InsertCharPre", EVENT_INSERTCHARPRE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007733 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007734 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7735 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar3b53dfb2012-06-06 18:03:07 +02007736 {"QuitPre", EVENT_QUITPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007737 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007738 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007739 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7740 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007741 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007742 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007743 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007744 {"StdinReadPost", EVENT_STDINREADPOST},
7745 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007746 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007747 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007748 {"TabEnter", EVENT_TABENTER},
7749 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007750 {"TermChanged", EVENT_TERMCHANGED},
7751 {"TermResponse", EVENT_TERMRESPONSE},
Bram Moolenaar186628f2013-03-19 13:33:23 +01007752 {"TextChanged", EVENT_TEXTCHANGED},
7753 {"TextChangedI", EVENT_TEXTCHANGEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007754 {"User", EVENT_USER},
7755 {"VimEnter", EVENT_VIMENTER},
7756 {"VimLeave", EVENT_VIMLEAVE},
7757 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7758 {"WinEnter", EVENT_WINENTER},
7759 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007760 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007761 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007762};
7763
7764static AutoPat *first_autopat[NUM_EVENTS] =
7765{
7766 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7767 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7768 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7769 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007770 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7771 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007772};
7773
7774/*
7775 * struct used to keep status while executing autocommands for an event.
7776 */
7777typedef struct AutoPatCmd
7778{
7779 AutoPat *curpat; /* next AutoPat to examine */
7780 AutoCmd *nextcmd; /* next AutoCmd to execute */
7781 int group; /* group being used */
7782 char_u *fname; /* fname to match with */
7783 char_u *sfname; /* sfname to match with */
7784 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007785 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007786 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7787 buf is deleted */
7788 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007789} AutoPatCmd;
7790
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007791static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007792
Bram Moolenaar071d4272004-06-13 20:20:40 +00007793/*
7794 * augroups stores a list of autocmd group names.
7795 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007796static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007797#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7798
7799/*
7800 * The ID of the current group. Group 0 is the default one.
7801 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007802static int current_augroup = AUGROUP_DEFAULT;
7803
7804static int au_need_clean = FALSE; /* need to delete marked patterns */
7805
Bram Moolenaar754b5602006-02-09 23:53:20 +00007806static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007807static void au_remove_pat __ARGS((AutoPat *ap));
7808static void au_remove_cmds __ARGS((AutoPat *ap));
7809static void au_cleanup __ARGS((void));
7810static int au_new_group __ARGS((char_u *name));
7811static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007812static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7813static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007814static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007815static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007816static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007817static 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 +00007818static 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 +00007819static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7820
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007821
Bram Moolenaar754b5602006-02-09 23:53:20 +00007822static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007823static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007824static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007825
7826/*
7827 * Show the autocommands for one AutoPat.
7828 */
7829 static void
7830show_autocmd(ap, event)
7831 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007832 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007833{
7834 AutoCmd *ac;
7835
7836 /* Check for "got_int" (here and at various places below), which is set
7837 * when "q" has been hit for the "--more--" prompt */
7838 if (got_int)
7839 return;
7840 if (ap->pat == NULL) /* pattern has been removed */
7841 return;
7842
7843 msg_putchar('\n');
7844 if (got_int)
7845 return;
7846 if (event != last_event || ap->group != last_group)
7847 {
7848 if (ap->group != AUGROUP_DEFAULT)
7849 {
7850 if (AUGROUP_NAME(ap->group) == NULL)
7851 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7852 else
7853 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7854 msg_puts((char_u *)" ");
7855 }
7856 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7857 last_event = event;
7858 last_group = ap->group;
7859 msg_putchar('\n');
7860 if (got_int)
7861 return;
7862 }
7863 msg_col = 4;
7864 msg_outtrans(ap->pat);
7865
7866 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7867 {
7868 if (ac->cmd != NULL) /* skip removed commands */
7869 {
7870 if (msg_col >= 14)
7871 msg_putchar('\n');
7872 msg_col = 14;
7873 if (got_int)
7874 return;
7875 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007876#ifdef FEAT_EVAL
7877 if (p_verbose > 0)
7878 last_set_msg(ac->scriptID);
7879#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007880 if (got_int)
7881 return;
7882 if (ac->next != NULL)
7883 {
7884 msg_putchar('\n');
7885 if (got_int)
7886 return;
7887 }
7888 }
7889 }
7890}
7891
7892/*
7893 * Mark an autocommand pattern for deletion.
7894 */
7895 static void
7896au_remove_pat(ap)
7897 AutoPat *ap;
7898{
7899 vim_free(ap->pat);
7900 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007901 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007902 au_need_clean = TRUE;
7903}
7904
7905/*
7906 * Mark all commands for a pattern for deletion.
7907 */
7908 static void
7909au_remove_cmds(ap)
7910 AutoPat *ap;
7911{
7912 AutoCmd *ac;
7913
7914 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7915 {
7916 vim_free(ac->cmd);
7917 ac->cmd = NULL;
7918 }
7919 au_need_clean = TRUE;
7920}
7921
7922/*
7923 * Cleanup autocommands and patterns that have been deleted.
7924 * This is only done when not executing autocommands.
7925 */
7926 static void
7927au_cleanup()
7928{
7929 AutoPat *ap, **prev_ap;
7930 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007931 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007932
7933 if (autocmd_busy || !au_need_clean)
7934 return;
7935
7936 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007937 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7938 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007939 {
7940 /* loop over all autocommand patterns */
7941 prev_ap = &(first_autopat[(int)event]);
7942 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7943 {
7944 /* loop over all commands for this pattern */
7945 prev_ac = &(ap->cmds);
7946 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7947 {
7948 /* remove the command if the pattern is to be deleted or when
7949 * the command has been marked for deletion */
7950 if (ap->pat == NULL || ac->cmd == NULL)
7951 {
7952 *prev_ac = ac->next;
7953 vim_free(ac->cmd);
7954 vim_free(ac);
7955 }
7956 else
7957 prev_ac = &(ac->next);
7958 }
7959
7960 /* remove the pattern if it has been marked for deletion */
7961 if (ap->pat == NULL)
7962 {
7963 *prev_ap = ap->next;
Bram Moolenaar473de612013-06-08 18:19:48 +02007964 vim_regfree(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007965 vim_free(ap);
7966 }
7967 else
7968 prev_ap = &(ap->next);
7969 }
7970 }
7971
7972 au_need_clean = FALSE;
7973}
7974
7975/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007976 * Called when buffer is freed, to remove/invalidate related buffer-local
7977 * autocmds.
7978 */
7979 void
7980aubuflocal_remove(buf)
7981 buf_T *buf;
7982{
7983 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007984 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007985 AutoPatCmd *apc;
7986
7987 /* invalidate currently executing autocommands */
7988 for (apc = active_apc_list; apc; apc = apc->next)
7989 if (buf->b_fnum == apc->arg_bufnr)
7990 apc->arg_bufnr = 0;
7991
7992 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007993 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7994 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007995 /* loop over all autocommand patterns */
7996 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7997 if (ap->buflocal_nr == buf->b_fnum)
7998 {
7999 au_remove_pat(ap);
8000 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008001 {
8002 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008003 smsg((char_u *)
8004 _("auto-removing autocommand: %s <buffer=%d>"),
8005 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008006 verbose_leave();
8007 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008008 }
8009 au_cleanup();
8010}
8011
8012/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008013 * Add an autocmd group name.
8014 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8015 */
8016 static int
8017au_new_group(name)
8018 char_u *name;
8019{
8020 int i;
8021
8022 i = au_find_group(name);
8023 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
8024 {
8025 /* First try using a free entry. */
8026 for (i = 0; i < augroups.ga_len; ++i)
8027 if (AUGROUP_NAME(i) == NULL)
8028 break;
8029 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
8030 return AUGROUP_ERROR;
8031
8032 AUGROUP_NAME(i) = vim_strsave(name);
8033 if (AUGROUP_NAME(i) == NULL)
8034 return AUGROUP_ERROR;
8035 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008036 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008037 }
8038
8039 return i;
8040}
8041
8042 static void
8043au_del_group(name)
8044 char_u *name;
8045{
8046 int i;
8047
8048 i = au_find_group(name);
8049 if (i == AUGROUP_ERROR) /* the group doesn't exist */
8050 EMSG2(_("E367: No such group: \"%s\""), name);
8051 else
8052 {
8053 vim_free(AUGROUP_NAME(i));
8054 AUGROUP_NAME(i) = NULL;
8055 }
8056}
8057
8058/*
8059 * Find the ID of an autocmd group name.
8060 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
8061 */
8062 static int
8063au_find_group(name)
8064 char_u *name;
8065{
8066 int i;
8067
8068 for (i = 0; i < augroups.ga_len; ++i)
8069 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
8070 return i;
8071 return AUGROUP_ERROR;
8072}
8073
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008074/*
8075 * Return TRUE if augroup "name" exists.
8076 */
8077 int
8078au_has_group(name)
8079 char_u *name;
8080{
8081 return au_find_group(name) != AUGROUP_ERROR;
8082}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00008083
Bram Moolenaar071d4272004-06-13 20:20:40 +00008084/*
8085 * ":augroup {name}".
8086 */
8087 void
8088do_augroup(arg, del_group)
8089 char_u *arg;
8090 int del_group;
8091{
8092 int i;
8093
8094 if (del_group)
8095 {
8096 if (*arg == NUL)
8097 EMSG(_(e_argreq));
8098 else
8099 au_del_group(arg);
8100 }
8101 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
8102 current_augroup = AUGROUP_DEFAULT;
8103 else if (*arg) /* ":aug xxx": switch to group xxx */
8104 {
8105 i = au_new_group(arg);
8106 if (i != AUGROUP_ERROR)
8107 current_augroup = i;
8108 }
8109 else /* ":aug": list the group names */
8110 {
8111 msg_start();
8112 for (i = 0; i < augroups.ga_len; ++i)
8113 {
8114 if (AUGROUP_NAME(i) != NULL)
8115 {
8116 msg_puts(AUGROUP_NAME(i));
8117 msg_puts((char_u *)" ");
8118 }
8119 }
8120 msg_clr_eos();
8121 msg_end();
8122 }
8123}
8124
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008125#if defined(EXITFREE) || defined(PROTO)
8126 void
8127free_all_autocmds()
8128{
8129 for (current_augroup = -1; current_augroup < augroups.ga_len;
8130 ++current_augroup)
8131 do_autocmd((char_u *)"", TRUE);
8132 ga_clear_strings(&augroups);
8133}
8134#endif
8135
Bram Moolenaar071d4272004-06-13 20:20:40 +00008136/*
8137 * Return the event number for event name "start".
8138 * Return NUM_EVENTS if the event name was not found.
8139 * Return a pointer to the next event name in "end".
8140 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008141 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00008142event_name2nr(start, end)
8143 char_u *start;
8144 char_u **end;
8145{
8146 char_u *p;
8147 int i;
8148 int len;
8149
8150 /* the event name ends with end of line, a blank or a comma */
8151 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
8152 ;
8153 for (i = 0; event_names[i].name != NULL; ++i)
8154 {
8155 len = (int)STRLEN(event_names[i].name);
8156 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
8157 break;
8158 }
8159 if (*p == ',')
8160 ++p;
8161 *end = p;
8162 if (event_names[i].name == NULL)
8163 return NUM_EVENTS;
8164 return event_names[i].event;
8165}
8166
8167/*
8168 * Return the name for event "event".
8169 */
8170 static char_u *
8171event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008172 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008173{
8174 int i;
8175
8176 for (i = 0; event_names[i].name != NULL; ++i)
8177 if (event_names[i].event == event)
8178 return (char_u *)event_names[i].name;
8179 return (char_u *)"Unknown";
8180}
8181
8182/*
8183 * Scan over the events. "*" stands for all events.
8184 */
8185 static char_u *
8186find_end_event(arg, have_group)
8187 char_u *arg;
8188 int have_group; /* TRUE when group name was found */
8189{
8190 char_u *pat;
8191 char_u *p;
8192
8193 if (*arg == '*')
8194 {
8195 if (arg[1] && !vim_iswhite(arg[1]))
8196 {
8197 EMSG2(_("E215: Illegal character after *: %s"), arg);
8198 return NULL;
8199 }
8200 pat = arg + 1;
8201 }
8202 else
8203 {
8204 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
8205 {
8206 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
8207 {
8208 if (have_group)
8209 EMSG2(_("E216: No such event: %s"), pat);
8210 else
8211 EMSG2(_("E216: No such group or event: %s"), pat);
8212 return NULL;
8213 }
8214 }
8215 }
8216 return pat;
8217}
8218
8219/*
8220 * Return TRUE if "event" is included in 'eventignore'.
8221 */
8222 static int
8223event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008224 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008225{
8226 char_u *p = p_ei;
8227
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008228 while (*p != NUL)
8229 {
8230 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8231 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008232 if (event_name2nr(p, &p) == event)
8233 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008234 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008235
8236 return FALSE;
8237}
8238
8239/*
8240 * Return OK when the contents of p_ei is valid, FAIL otherwise.
8241 */
8242 int
8243check_ei()
8244{
8245 char_u *p = p_ei;
8246
Bram Moolenaar071d4272004-06-13 20:20:40 +00008247 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008248 {
8249 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
8250 {
8251 p += 3;
8252 if (*p == ',')
8253 ++p;
8254 }
8255 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008256 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00008257 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008258
8259 return OK;
8260}
8261
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008262# if defined(FEAT_SYN_HL) || defined(PROTO)
8263
8264/*
8265 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
8266 * buffer loaded into the window. "what" must start with a comma.
8267 * Returns the old value of 'eventignore' in allocated memory.
8268 */
8269 char_u *
8270au_event_disable(what)
8271 char *what;
8272{
8273 char_u *new_ei;
8274 char_u *save_ei;
8275
8276 save_ei = vim_strsave(p_ei);
8277 if (save_ei != NULL)
8278 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008279 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008280 if (new_ei != NULL)
8281 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008282 if (*what == ',' && *p_ei == NUL)
8283 STRCPY(new_ei, what + 1);
8284 else
8285 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008286 set_string_option_direct((char_u *)"ei", -1, new_ei,
8287 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008288 vim_free(new_ei);
8289 }
8290 }
8291 return save_ei;
8292}
8293
8294 void
8295au_event_restore(old_ei)
8296 char_u *old_ei;
8297{
8298 if (old_ei != NULL)
8299 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008300 set_string_option_direct((char_u *)"ei", -1, old_ei,
8301 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008302 vim_free(old_ei);
8303 }
8304}
8305# endif /* FEAT_SYN_HL */
8306
Bram Moolenaar071d4272004-06-13 20:20:40 +00008307/*
8308 * do_autocmd() -- implements the :autocmd command. Can be used in the
8309 * following ways:
8310 *
8311 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8312 * will be automatically executed for <event>
8313 * when editing a file matching <pat>, in
8314 * the current group.
8315 * :autocmd <event> <pat> Show the auto-commands associated with
8316 * <event> and <pat>.
8317 * :autocmd <event> Show the auto-commands associated with
8318 * <event>.
8319 * :autocmd Show all auto-commands.
8320 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
8321 * <event> and <pat>, and add the command
8322 * <cmd>, for the current group.
8323 * :autocmd! <event> <pat> Remove all auto-commands associated with
8324 * <event> and <pat> for the current group.
8325 * :autocmd! <event> Remove all auto-commands associated with
8326 * <event> for the current group.
8327 * :autocmd! Remove ALL auto-commands for the current
8328 * group.
8329 *
8330 * Multiple events and patterns may be given separated by commas. Here are
8331 * some examples:
8332 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8333 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8334 *
8335 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008336 *
8337 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008338 */
8339 void
8340do_autocmd(arg, forceit)
8341 char_u *arg;
8342 int forceit;
8343{
8344 char_u *pat;
8345 char_u *envpat = NULL;
8346 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008347 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008348 int need_free = FALSE;
8349 int nested = FALSE;
8350 int group;
8351
8352 /*
8353 * Check for a legal group name. If not, use AUGROUP_ALL.
8354 */
8355 group = au_get_grouparg(&arg);
8356 if (arg == NULL) /* out of memory */
8357 return;
8358
8359 /*
8360 * Scan over the events.
8361 * If we find an illegal name, return here, don't do anything.
8362 */
8363 pat = find_end_event(arg, group != AUGROUP_ALL);
8364 if (pat == NULL)
8365 return;
8366
8367 /*
8368 * Scan over the pattern. Put a NUL at the end.
8369 */
8370 pat = skipwhite(pat);
8371 cmd = pat;
8372 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
8373 cmd++;
8374 if (*cmd)
8375 *cmd++ = NUL;
8376
8377 /* Expand environment variables in the pattern. Set 'shellslash', we want
8378 * forward slashes here. */
8379 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8380 {
8381#ifdef BACKSLASH_IN_FILENAME
8382 int p_ssl_save = p_ssl;
8383
8384 p_ssl = TRUE;
8385#endif
8386 envpat = expand_env_save(pat);
8387#ifdef BACKSLASH_IN_FILENAME
8388 p_ssl = p_ssl_save;
8389#endif
8390 if (envpat != NULL)
8391 pat = envpat;
8392 }
8393
8394 /*
8395 * Check for "nested" flag.
8396 */
8397 cmd = skipwhite(cmd);
8398 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
8399 {
8400 nested = TRUE;
8401 cmd = skipwhite(cmd + 6);
8402 }
8403
8404 /*
8405 * Find the start of the commands.
8406 * Expand <sfile> in it.
8407 */
8408 if (*cmd != NUL)
8409 {
8410 cmd = expand_sfile(cmd);
8411 if (cmd == NULL) /* some error */
8412 return;
8413 need_free = TRUE;
8414 }
8415
8416 /*
8417 * Print header when showing autocommands.
8418 */
8419 if (!forceit && *cmd == NUL)
8420 {
8421 /* Highlight title */
8422 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
8423 }
8424
8425 /*
8426 * Loop over the events.
8427 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008428 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008429 last_group = AUGROUP_ERROR; /* for listing the group name */
8430 if (*arg == '*' || *arg == NUL)
8431 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008432 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8433 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008434 if (do_autocmd_event(event, pat,
8435 nested, cmd, forceit, group) == FAIL)
8436 break;
8437 }
8438 else
8439 {
8440 while (*arg && !vim_iswhite(*arg))
8441 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8442 nested, cmd, forceit, group) == FAIL)
8443 break;
8444 }
8445
8446 if (need_free)
8447 vim_free(cmd);
8448 vim_free(envpat);
8449}
8450
8451/*
8452 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8453 * The "argp" argument is advanced to the following argument.
8454 *
8455 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8456 */
8457 static int
8458au_get_grouparg(argp)
8459 char_u **argp;
8460{
8461 char_u *group_name;
8462 char_u *p;
8463 char_u *arg = *argp;
8464 int group = AUGROUP_ALL;
8465
8466 p = skiptowhite(arg);
8467 if (p > arg)
8468 {
8469 group_name = vim_strnsave(arg, (int)(p - arg));
8470 if (group_name == NULL) /* out of memory */
8471 return AUGROUP_ERROR;
8472 group = au_find_group(group_name);
8473 if (group == AUGROUP_ERROR)
8474 group = AUGROUP_ALL; /* no match, use all groups */
8475 else
8476 *argp = skipwhite(p); /* match, skip over group name */
8477 vim_free(group_name);
8478 }
8479 return group;
8480}
8481
8482/*
8483 * do_autocmd() for one event.
8484 * If *pat == NUL do for all patterns.
8485 * If *cmd == NUL show entries.
8486 * If forceit == TRUE delete entries.
8487 * If group is not AUGROUP_ALL, only use this group.
8488 */
8489 static int
8490do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008491 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008492 char_u *pat;
8493 int nested;
8494 char_u *cmd;
8495 int forceit;
8496 int group;
8497{
8498 AutoPat *ap;
8499 AutoPat **prev_ap;
8500 AutoCmd *ac;
8501 AutoCmd **prev_ac;
8502 int brace_level;
8503 char_u *endpat;
8504 int findgroup;
8505 int allgroups;
8506 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008507 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008508 int buflocal_nr;
8509 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008510
8511 if (group == AUGROUP_ALL)
8512 findgroup = current_augroup;
8513 else
8514 findgroup = group;
8515 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8516
8517 /*
8518 * Show or delete all patterns for an event.
8519 */
8520 if (*pat == NUL)
8521 {
8522 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8523 {
8524 if (forceit) /* delete the AutoPat, if it's in the current group */
8525 {
8526 if (ap->group == findgroup)
8527 au_remove_pat(ap);
8528 }
8529 else if (group == AUGROUP_ALL || ap->group == group)
8530 show_autocmd(ap, event);
8531 }
8532 }
8533
8534 /*
8535 * Loop through all the specified patterns.
8536 */
8537 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8538 {
8539 /*
8540 * Find end of the pattern.
8541 * Watch out for a comma in braces, like "*.\{obj,o\}".
8542 */
8543 brace_level = 0;
8544 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
8545 || endpat[-1] == '\\'); ++endpat)
8546 {
8547 if (*endpat == '{')
8548 brace_level++;
8549 else if (*endpat == '}')
8550 brace_level--;
8551 }
8552 if (pat == endpat) /* ignore single comma */
8553 continue;
8554 patlen = (int)(endpat - pat);
8555
8556 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008557 * detect special <buflocal[=X]> buffer-local patterns
8558 */
8559 is_buflocal = FALSE;
8560 buflocal_nr = 0;
8561
8562 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
8563 && pat[patlen - 1] == '>')
8564 {
8565 /* Error will be printed only for addition. printing and removing
8566 * will proceed silently. */
8567 is_buflocal = TRUE;
8568 if (patlen == 8)
8569 buflocal_nr = curbuf->b_fnum;
8570 else if (patlen > 9 && pat[7] == '=')
8571 {
8572 /* <buffer=abuf> */
8573 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
8574 buflocal_nr = autocmd_bufnr;
8575 /* <buffer=123> */
8576 else if (skipdigits(pat + 8) == pat + patlen - 1)
8577 buflocal_nr = atoi((char *)pat + 8);
8578 }
8579 }
8580
8581 if (is_buflocal)
8582 {
8583 /* normalize pat into standard "<buffer>#N" form */
8584 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8585 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008586 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008587 }
8588
8589 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008590 * Find AutoPat entries with this pattern.
8591 */
8592 prev_ap = &first_autopat[(int)event];
8593 while ((ap = *prev_ap) != NULL)
8594 {
8595 if (ap->pat != NULL)
8596 {
8597 /* Accept a pattern when:
8598 * - a group was specified and it's that group, or a group was
8599 * not specified and it's the current group, or a group was
8600 * not specified and we are listing
8601 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008602 * - the pattern matches.
8603 * For <buffer[=X]>, this condition works because we normalize
8604 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008605 */
8606 if ((allgroups || ap->group == findgroup)
8607 && ap->patlen == patlen
8608 && STRNCMP(pat, ap->pat, patlen) == 0)
8609 {
8610 /*
8611 * Remove existing autocommands.
8612 * If adding any new autocmd's for this AutoPat, don't
8613 * delete the pattern from the autopat list, append to
8614 * this list.
8615 */
8616 if (forceit)
8617 {
8618 if (*cmd != NUL && ap->next == NULL)
8619 {
8620 au_remove_cmds(ap);
8621 break;
8622 }
8623 au_remove_pat(ap);
8624 }
8625
8626 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008627 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008628 */
8629 else if (*cmd == NUL)
8630 show_autocmd(ap, event);
8631
8632 /*
8633 * Add autocmd to this autopat, if it's the last one.
8634 */
8635 else if (ap->next == NULL)
8636 break;
8637 }
8638 }
8639 prev_ap = &ap->next;
8640 }
8641
8642 /*
8643 * Add a new command.
8644 */
8645 if (*cmd != NUL)
8646 {
8647 /*
8648 * If the pattern we want to add a command to does appear at the
8649 * end of the list (or not is not in the list at all), add the
8650 * pattern at the end of the list.
8651 */
8652 if (ap == NULL)
8653 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008654 /* refuse to add buffer-local ap if buffer number is invalid */
8655 if (is_buflocal && (buflocal_nr == 0
8656 || buflist_findnr(buflocal_nr) == NULL))
8657 {
8658 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
8659 buflocal_nr);
8660 return FAIL;
8661 }
8662
Bram Moolenaar071d4272004-06-13 20:20:40 +00008663 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8664 if (ap == NULL)
8665 return FAIL;
8666 ap->pat = vim_strnsave(pat, patlen);
8667 ap->patlen = patlen;
8668 if (ap->pat == NULL)
8669 {
8670 vim_free(ap);
8671 return FAIL;
8672 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008673
8674 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008675 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008676 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008677 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008678 }
8679 else
8680 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008681 char_u *reg_pat;
8682
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008683 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008684 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008685 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008686 if (reg_pat != NULL)
8687 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008688 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008689 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008690 {
8691 vim_free(ap->pat);
8692 vim_free(ap);
8693 return FAIL;
8694 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008695 }
8696 ap->cmds = NULL;
8697 *prev_ap = ap;
8698 ap->next = NULL;
8699 if (group == AUGROUP_ALL)
8700 ap->group = current_augroup;
8701 else
8702 ap->group = group;
8703 }
8704
8705 /*
8706 * Add the autocmd at the end of the AutoCmd list.
8707 */
8708 prev_ac = &(ap->cmds);
8709 while ((ac = *prev_ac) != NULL)
8710 prev_ac = &ac->next;
8711 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8712 if (ac == NULL)
8713 return FAIL;
8714 ac->cmd = vim_strsave(cmd);
8715#ifdef FEAT_EVAL
8716 ac->scriptID = current_SID;
8717#endif
8718 if (ac->cmd == NULL)
8719 {
8720 vim_free(ac);
8721 return FAIL;
8722 }
8723 ac->next = NULL;
8724 *prev_ac = ac;
8725 ac->nested = nested;
8726 }
8727 }
8728
8729 au_cleanup(); /* may really delete removed patterns/commands now */
8730 return OK;
8731}
8732
8733/*
8734 * Implementation of ":doautocmd [group] event [fname]".
8735 * Return OK for success, FAIL for failure;
8736 */
8737 int
8738do_doautocmd(arg, do_msg)
8739 char_u *arg;
8740 int do_msg; /* give message for no matching autocmds? */
8741{
8742 char_u *fname;
8743 int nothing_done = TRUE;
8744 int group;
8745
8746 /*
8747 * Check for a legal group name. If not, use AUGROUP_ALL.
8748 */
8749 group = au_get_grouparg(&arg);
8750 if (arg == NULL) /* out of memory */
8751 return FAIL;
8752
8753 if (*arg == '*')
8754 {
8755 EMSG(_("E217: Can't execute autocommands for ALL events"));
8756 return FAIL;
8757 }
8758
8759 /*
8760 * Scan over the events.
8761 * If we find an illegal name, return here, don't do anything.
8762 */
8763 fname = find_end_event(arg, group != AUGROUP_ALL);
8764 if (fname == NULL)
8765 return FAIL;
8766
8767 fname = skipwhite(fname);
8768
8769 /*
8770 * Loop over the events.
8771 */
8772 while (*arg && !vim_iswhite(*arg))
8773 if (apply_autocmds_group(event_name2nr(arg, &arg),
8774 fname, NULL, TRUE, group, curbuf, NULL))
8775 nothing_done = FALSE;
8776
8777 if (nothing_done && do_msg)
8778 MSG(_("No matching autocommands"));
8779
8780#ifdef FEAT_EVAL
8781 return aborting() ? FAIL : OK;
8782#else
8783 return OK;
8784#endif
8785}
8786
8787/*
8788 * ":doautoall": execute autocommands for each loaded buffer.
8789 */
8790 void
8791ex_doautoall(eap)
8792 exarg_T *eap;
8793{
8794 int retval;
8795 aco_save_T aco;
8796 buf_T *buf;
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008797 char_u *arg = eap->arg;
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008798 int call_do_modelines = check_nomodeline(&arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008799
8800 /*
8801 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8802 * equal to curbuf, but for some buffers there may not be a window.
8803 * So we change the buffer for the current window for a moment. This
8804 * gives problems when the autocommands make changes to the list of
8805 * buffers or windows...
8806 */
8807 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8808 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008809 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810 {
8811 /* find a window for this buffer and save some values */
8812 aucmd_prepbuf(&aco, buf);
8813
8814 /* execute the autocommands for this buffer */
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008815 retval = do_doautocmd(arg, FALSE);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008816
Bram Moolenaara61d5fb2012-02-12 00:18:58 +01008817 if (call_do_modelines)
8818 {
8819 /* Execute the modeline settings, but don't set window-local
8820 * options if we are using the current window for another
8821 * buffer. */
8822 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
8823 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008824
8825 /* restore the current window */
8826 aucmd_restbuf(&aco);
8827
8828 /* stop if there is some error or buffer was deleted */
8829 if (retval == FAIL || !buf_valid(buf))
8830 break;
8831 }
8832 }
8833
8834 check_cursor(); /* just in case lines got deleted */
8835}
8836
8837/*
Bram Moolenaar60542ac2012-02-12 20:14:01 +01008838 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
8839 * return TRUE and advance *argp to after it.
8840 * Thus return TRUE when do_modelines() should be called.
8841 */
8842 int
8843check_nomodeline(argp)
8844 char_u **argp;
8845{
8846 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
8847 {
8848 *argp = skipwhite(*argp + 12);
8849 return FALSE;
8850 }
8851 return TRUE;
8852}
8853
8854/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008855 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008856 * Search for a visible window containing the current buffer. If there isn't
8857 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008858 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008859 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008860 */
8861 void
8862aucmd_prepbuf(aco, buf)
8863 aco_save_T *aco; /* structure to save values in */
8864 buf_T *buf; /* new curbuf */
8865{
8866 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008867#ifdef FEAT_WINDOWS
8868 int save_ea;
8869#endif
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008870#ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008871 int save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008872#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008873
8874 /* Find a window that is for the new buffer */
8875 if (buf == curbuf) /* be quick when buf is curbuf */
8876 win = curwin;
8877 else
8878#ifdef FEAT_WINDOWS
8879 for (win = firstwin; win != NULL; win = win->w_next)
8880 if (win->w_buffer == buf)
8881 break;
8882#else
8883 win = NULL;
8884#endif
8885
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008886 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
8887 * back to using the current window. */
8888 if (win == NULL && aucmd_win == NULL)
8889 {
8890 win_alloc_aucmd_win();
8891 if (aucmd_win == NULL)
8892 win = curwin;
8893 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008894 if (win == NULL && aucmd_win_used)
8895 /* Strange recursive autocommand, fall back to using the current
8896 * window. Expect a few side effects... */
8897 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008898
8899 aco->save_curwin = curwin;
8900 aco->save_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008901 if (win != NULL)
8902 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008903 /* There is a window for "buf" in the current tab page, make it the
8904 * curwin. This is preferred, it has the least side effects (esp. if
8905 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008906 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008907 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008908 }
8909 else
8910 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008911 /* There is no window for "buf", use "aucmd_win". To minimize the side
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02008912 * effects, insert it in the current tab page.
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008913 * Anything related to a window (e.g., setting folds) may have
8914 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008915 aco->use_aucmd_win = TRUE;
8916 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008917 aucmd_win->w_buffer = buf;
Bram Moolenaarcdddaa42010-06-07 23:07:44 +02008918 aucmd_win->w_s = &buf->b_s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008919 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008920 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008921
8922 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
8923 * win_enter_ext(). */
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008924 vim_free(aucmd_win->w_localdir);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008925 aucmd_win->w_localdir = NULL;
8926 aco->globaldir = globaldir;
8927 globaldir = NULL;
8928
Bram Moolenaar071d4272004-06-13 20:20:40 +00008929
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008930#ifdef FEAT_WINDOWS
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008931 /* Split the current window, put the aucmd_win in the upper half.
8932 * We don't want the BufEnter or WinEnter autocommands. */
8933 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008934 make_snapshot(SNAP_AUCMD_IDX);
8935 save_ea = p_ea;
8936 p_ea = FALSE;
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008937
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008938# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008939 /* Prevent chdir() call in win_enter_ext(), through do_autochdir(). */
8940 save_acd = p_acd;
8941 p_acd = FALSE;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008942# endif
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008943
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008944 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
8945 (void)win_comp_pos(); /* recompute window positions */
8946 p_ea = save_ea;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008947# ifdef FEAT_AUTOCHDIR
Bram Moolenaar4008f4f2013-08-02 17:08:13 +02008948 p_acd = save_acd;
Bram Moolenaar01c458e2013-08-05 22:02:20 +02008949# endif
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008950 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008951#endif
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008952 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008953 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008954 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008955 aco->new_curwin = curwin;
8956 aco->new_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957}
8958
8959/*
8960 * Cleanup after executing autocommands for a (hidden) buffer.
8961 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008962 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008963 */
8964 void
8965aucmd_restbuf(aco)
8966 aco_save_T *aco; /* structure holding saved values */
8967{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008968#ifdef FEAT_WINDOWS
8969 int dummy;
8970#endif
8971
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008972 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008973 {
8974 --curbuf->b_nwindows;
8975#ifdef FEAT_WINDOWS
8976 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008977 * page. Do not trigger autocommands here. */
8978 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008979 if (curwin != aucmd_win)
8980 {
8981 tabpage_T *tp;
8982 win_T *wp;
8983
8984 FOR_ALL_TAB_WINDOWS(tp, wp)
8985 {
8986 if (wp == aucmd_win)
8987 {
8988 if (tp != curtab)
Bram Moolenaar49e649f2013-05-06 04:50:35 +02008989 goto_tabpage_tp(tp, TRUE, TRUE);
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008990 win_goto(aucmd_win);
Bram Moolenaar28f29082012-02-11 23:45:37 +01008991 goto win_found;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008992 }
8993 }
8994 }
Bram Moolenaar28f29082012-02-11 23:45:37 +01008995win_found:
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008996
8997 /* Remove the window and frame from the tree of frames. */
8998 (void)winframe_remove(curwin, &dummy, NULL);
8999 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009000 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009001 last_status(FALSE); /* may need to remove last status line */
9002 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
9003 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00009004 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009005
9006 if (win_valid(aco->save_curwin))
9007 curwin = aco->save_curwin;
9008 else
9009 /* Hmm, original window disappeared. Just use the first one. */
9010 curwin = firstwin;
9011# ifdef FEAT_EVAL
Bram Moolenaar429fa852013-04-15 12:27:36 +02009012 vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
9013 hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009014# endif
9015#else
9016 curwin = aco->save_curwin;
9017#endif
9018 curbuf = curwin->w_buffer;
9019
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009020 vim_free(globaldir);
9021 globaldir = aco->globaldir;
9022
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009023 /* the buffer contents may have changed */
9024 check_cursor();
9025 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
9026 {
9027 curwin->w_topline = curbuf->b_ml.ml_line_count;
9028#ifdef FEAT_DIFF
9029 curwin->w_topfill = 0;
9030#endif
9031 }
9032#if defined(FEAT_GUI)
9033 /* Hide the scrollbars from the aucmd_win and update. */
9034 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
9035 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
9036 gui_may_update_scrollbars();
9037#endif
9038 }
9039 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009040 {
9041 /* restore curwin */
9042#ifdef FEAT_WINDOWS
9043 if (win_valid(aco->save_curwin))
9044#endif
9045 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009046 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00009047 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009048 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009049 if (curwin == aco->new_curwin
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009050 && curbuf != aco->new_curbuf
9051 && buf_valid(aco->new_curbuf)
9052 && aco->new_curbuf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009053 {
Bram Moolenaar7da9c372012-04-30 17:04:52 +02009054# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
9055 if (curwin->w_s == &curbuf->b_s)
9056 curwin->w_s = &aco->new_curbuf->b_s;
9057# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009058 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009059 curbuf = aco->new_curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009060 curwin->w_buffer = curbuf;
9061 ++curbuf->b_nwindows;
9062 }
9063
9064 curwin = aco->save_curwin;
9065 curbuf = curwin->w_buffer;
9066 }
9067 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009068}
9069
9070static int autocmd_nested = FALSE;
9071
9072/*
9073 * Execute autocommands for "event" and file name "fname".
9074 * Return TRUE if some commands were executed.
9075 */
9076 int
9077apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009078 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009079 char_u *fname; /* NULL or empty means use actual file name */
9080 char_u *fname_io; /* fname to use for <afile> on cmdline */
9081 int force; /* when TRUE, ignore autocmd_busy */
9082 buf_T *buf; /* buffer for <abuf> */
9083{
9084 return apply_autocmds_group(event, fname, fname_io, force,
9085 AUGROUP_ALL, buf, NULL);
9086}
9087
9088/*
9089 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
9090 * setting v:filearg.
9091 */
9092 static int
9093apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009094 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009095 char_u *fname;
9096 char_u *fname_io;
9097 int force;
9098 buf_T *buf;
9099 exarg_T *eap;
9100{
9101 return apply_autocmds_group(event, fname, fname_io, force,
9102 AUGROUP_ALL, buf, eap);
9103}
9104
9105/*
9106 * Like apply_autocmds(), but handles the caller's retval. If the script
9107 * processing is being aborted or if retval is FAIL when inside a try
9108 * conditional, no autocommands are executed. If otherwise the autocommands
9109 * cause the script to be aborted, retval is set to FAIL.
9110 */
9111 int
9112apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009113 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009114 char_u *fname; /* NULL or empty means use actual file name */
9115 char_u *fname_io; /* fname to use for <afile> on cmdline */
9116 int force; /* when TRUE, ignore autocmd_busy */
9117 buf_T *buf; /* buffer for <abuf> */
9118 int *retval; /* pointer to caller's retval */
9119{
9120 int did_cmd;
9121
Bram Moolenaar1e015462005-09-25 22:16:38 +00009122#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009123 if (should_abort(*retval))
9124 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00009125#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009126
9127 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
9128 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00009129 if (did_cmd
9130#ifdef FEAT_EVAL
9131 && aborting()
9132#endif
9133 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00009134 *retval = FAIL;
9135 return did_cmd;
9136}
9137
Bram Moolenaard35f9712005-12-18 22:02:33 +00009138/*
9139 * Return TRUE when there is a CursorHold autocommand defined.
9140 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009141 int
9142has_cursorhold()
9143{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009144 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
9145 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009146}
Bram Moolenaard35f9712005-12-18 22:02:33 +00009147
9148/*
9149 * Return TRUE if the CursorHold event can be triggered.
9150 */
9151 int
9152trigger_cursorhold()
9153{
Bram Moolenaar754b5602006-02-09 23:53:20 +00009154 int state;
9155
Bram Moolenaar05334432011-07-20 18:29:39 +02009156 if (!did_cursorhold
9157 && has_cursorhold()
9158 && !Recording
9159 && typebuf.tb_len == 0
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00009160#ifdef FEAT_INS_EXPAND
9161 && !ins_compl_active()
9162#endif
9163 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00009164 {
9165 state = get_real_state();
9166 if (state == NORMAL_BUSY || (state & INSERT) != 0)
9167 return TRUE;
9168 }
9169 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00009170}
Bram Moolenaar754b5602006-02-09 23:53:20 +00009171
9172/*
9173 * Return TRUE when there is a CursorMoved autocommand defined.
9174 */
9175 int
9176has_cursormoved()
9177{
9178 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
9179}
9180
9181/*
9182 * Return TRUE when there is a CursorMovedI autocommand defined.
9183 */
9184 int
9185has_cursormovedI()
9186{
9187 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
9188}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009189
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009190/*
Bram Moolenaar186628f2013-03-19 13:33:23 +01009191 * Return TRUE when there is a TextChanged autocommand defined.
9192 */
9193 int
9194has_textchanged()
9195{
9196 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
9197}
9198
9199/*
9200 * Return TRUE when there is a TextChangedI autocommand defined.
9201 */
9202 int
9203has_textchangedI()
9204{
9205 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
9206}
9207
9208/*
Bram Moolenaarf5876f12012-02-29 18:22:08 +01009209 * Return TRUE when there is an InsertCharPre autocommand defined.
9210 */
9211 int
9212has_insertcharpre()
9213{
9214 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
9215}
9216
Bram Moolenaar071d4272004-06-13 20:20:40 +00009217 static int
9218apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009219 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009220 char_u *fname; /* NULL or empty means use actual file name */
9221 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
9222 use fname */
9223 int force; /* when TRUE, ignore autocmd_busy */
9224 int group; /* group ID, or AUGROUP_ALL */
9225 buf_T *buf; /* buffer for <abuf> */
9226 exarg_T *eap; /* command arguments */
9227{
9228 char_u *sfname = NULL; /* short file name */
9229 char_u *tail;
9230 int save_changed;
9231 buf_T *old_curbuf;
9232 int retval = FALSE;
9233 char_u *save_sourcing_name;
9234 linenr_T save_sourcing_lnum;
9235 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009236 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009237 int save_autocmd_bufnr;
9238 char_u *save_autocmd_match;
9239 int save_autocmd_busy;
9240 int save_autocmd_nested;
9241 static int nesting = 0;
9242 AutoPatCmd patcmd;
9243 AutoPat *ap;
9244#ifdef FEAT_EVAL
9245 scid_T save_current_SID;
9246 void *save_funccalp;
9247 char_u *save_cmdarg;
9248 long save_cmdbang;
9249#endif
9250 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00009251#ifdef FEAT_PROFILE
9252 proftime_T wait_time;
9253#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009254
9255 /*
9256 * Quickly return if there are no autocommands for this event or
9257 * autocommands are blocked.
9258 */
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009259 if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009260 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009261
9262 /*
9263 * When autocommands are busy, new autocommands are only executed when
9264 * explicitly enabled with the "nested" flag.
9265 */
9266 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009267 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009268
9269#ifdef FEAT_EVAL
9270 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00009271 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00009272 * occurred or an exception was thrown but not caught.
9273 */
9274 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009275 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009276#endif
9277
9278 /*
9279 * FileChangedShell never nests, because it can create an endless loop.
9280 */
Bram Moolenaar56718732006-03-15 22:53:57 +00009281 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
9282 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009283 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009284
9285 /*
9286 * Ignore events in 'eventignore'.
9287 */
9288 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009289 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009290
9291 /*
9292 * Allow nesting of autocommands, but restrict the depth, because it's
9293 * possible to create an endless loop.
9294 */
9295 if (nesting == 10)
9296 {
9297 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009298 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009299 }
9300
9301 /*
9302 * Check if these autocommands are disabled. Used when doing ":all" or
9303 * ":ball".
9304 */
9305 if ( (autocmd_no_enter
9306 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
9307 || (autocmd_no_leave
9308 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009309 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009310
9311 /*
9312 * Save the autocmd_* variables and info about the current buffer.
9313 */
9314 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009315 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009316 save_autocmd_bufnr = autocmd_bufnr;
9317 save_autocmd_match = autocmd_match;
9318 save_autocmd_busy = autocmd_busy;
9319 save_autocmd_nested = autocmd_nested;
9320 save_changed = curbuf->b_changed;
9321 old_curbuf = curbuf;
9322
9323 /*
9324 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00009325 * Make a copy to avoid that changing a buffer name or directory makes it
9326 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009327 */
9328 if (fname_io == NULL)
9329 {
9330 if (fname != NULL && *fname != NUL)
9331 autocmd_fname = fname;
9332 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009333 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009334 else
9335 autocmd_fname = NULL;
9336 }
9337 else
9338 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009339 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009340 autocmd_fname = vim_strsave(autocmd_fname);
9341 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009342
9343 /*
9344 * Set the buffer number to be used for <abuf>.
9345 */
9346 if (buf == NULL)
9347 autocmd_bufnr = 0;
9348 else
9349 autocmd_bufnr = buf->b_fnum;
9350
9351 /*
9352 * When the file name is NULL or empty, use the file name of buffer "buf".
9353 * Always use the full path of the file name to match with, in case
9354 * "allow_dirs" is set.
9355 */
9356 if (fname == NULL || *fname == NUL)
9357 {
9358 if (buf == NULL)
9359 fname = NULL;
9360 else
9361 {
9362#ifdef FEAT_SYN_HL
9363 if (event == EVENT_SYNTAX)
9364 fname = buf->b_p_syn;
9365 else
9366#endif
9367 if (event == EVENT_FILETYPE)
9368 fname = buf->b_p_ft;
9369 else
9370 {
9371 if (buf->b_sfname != NULL)
9372 sfname = vim_strsave(buf->b_sfname);
9373 fname = buf->b_ffname;
9374 }
9375 }
9376 if (fname == NULL)
9377 fname = (char_u *)"";
9378 fname = vim_strsave(fname); /* make a copy, so we can change it */
9379 }
9380 else
9381 {
9382 sfname = vim_strsave(fname);
Bram Moolenaar5135d462009-04-29 16:03:38 +00009383 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID or
9384 * QuickFixCmd* */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009385 if (event == EVENT_FILETYPE
9386 || event == EVENT_SYNTAX
Bram Moolenaar5135d462009-04-29 16:03:38 +00009387 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009388 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009389 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009390 || event == EVENT_QUICKFIXCMDPRE
9391 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009392 fname = vim_strsave(fname);
9393 else
9394 fname = FullName_save(fname, FALSE);
9395 }
9396 if (fname == NULL) /* out of memory */
9397 {
9398 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009399 retval = FALSE;
9400 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009401 }
9402
9403#ifdef BACKSLASH_IN_FILENAME
9404 /*
9405 * Replace all backslashes with forward slashes. This makes the
9406 * autocommand patterns portable between Unix and MS-DOS.
9407 */
9408 if (sfname != NULL)
9409 forward_slash(sfname);
9410 forward_slash(fname);
9411#endif
9412
9413#ifdef VMS
9414 /* remove version for correct match */
9415 if (sfname != NULL)
9416 vms_remove_version(sfname);
9417 vms_remove_version(fname);
9418#endif
9419
9420 /*
9421 * Set the name to be used for <amatch>.
9422 */
9423 autocmd_match = fname;
9424
9425
9426 /* Don't redraw while doing auto commands. */
9427 ++RedrawingDisabled;
9428 save_sourcing_name = sourcing_name;
9429 sourcing_name = NULL; /* don't free this one */
9430 save_sourcing_lnum = sourcing_lnum;
9431 sourcing_lnum = 0; /* no line number here */
9432
9433#ifdef FEAT_EVAL
9434 save_current_SID = current_SID;
9435
Bram Moolenaar05159a02005-02-26 23:04:13 +00009436# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009437 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009438 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9439# endif
9440
Bram Moolenaar071d4272004-06-13 20:20:40 +00009441 /* Don't use local function variables, if called from a function */
9442 save_funccalp = save_funccal();
9443#endif
9444
9445 /*
9446 * When starting to execute autocommands, save the search patterns.
9447 */
9448 if (!autocmd_busy)
9449 {
9450 save_search_patterns();
9451 saveRedobuff();
9452 did_filetype = keep_filetype;
9453 }
9454
9455 /*
9456 * Note that we are applying autocmds. Some commands need to know.
9457 */
9458 autocmd_busy = TRUE;
9459 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9460 ++nesting; /* see matching decrement below */
9461
9462 /* Remember that FileType was triggered. Used for did_filetype(). */
9463 if (event == EVENT_FILETYPE)
9464 did_filetype = TRUE;
9465
9466 tail = gettail(fname);
9467
9468 /* Find first autocommand that matches */
9469 patcmd.curpat = first_autopat[(int)event];
9470 patcmd.nextcmd = NULL;
9471 patcmd.group = group;
9472 patcmd.fname = fname;
9473 patcmd.sfname = sfname;
9474 patcmd.tail = tail;
9475 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009476 patcmd.arg_bufnr = autocmd_bufnr;
9477 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009478 auto_next_pat(&patcmd, FALSE);
9479
9480 /* found one, start executing the autocommands */
9481 if (patcmd.curpat != NULL)
9482 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009483 /* add to active_apc_list */
9484 patcmd.next = active_apc_list;
9485 active_apc_list = &patcmd;
9486
Bram Moolenaar071d4272004-06-13 20:20:40 +00009487#ifdef FEAT_EVAL
9488 /* set v:cmdarg (only when there is a matching pattern) */
9489 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
9490 if (eap != NULL)
9491 {
9492 save_cmdarg = set_cmdarg(eap, NULL);
9493 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9494 }
9495 else
9496 save_cmdarg = NULL; /* avoid gcc warning */
9497#endif
9498 retval = TRUE;
9499 /* mark the last pattern, to avoid an endless loop when more patterns
9500 * are added when executing autocommands */
9501 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9502 ap->last = FALSE;
9503 ap->last = TRUE;
9504 check_lnums(TRUE); /* make sure cursor and topline are valid */
9505 do_cmdline(NULL, getnextac, (void *)&patcmd,
9506 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9507#ifdef FEAT_EVAL
9508 if (eap != NULL)
9509 {
9510 (void)set_cmdarg(NULL, save_cmdarg);
9511 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9512 }
9513#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009514 /* delete from active_apc_list */
9515 if (active_apc_list == &patcmd) /* just in case */
9516 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009517 }
9518
9519 --RedrawingDisabled;
9520 autocmd_busy = save_autocmd_busy;
9521 filechangeshell_busy = FALSE;
9522 autocmd_nested = save_autocmd_nested;
9523 vim_free(sourcing_name);
9524 sourcing_name = save_sourcing_name;
9525 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009526 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009527 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009528 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009529 autocmd_bufnr = save_autocmd_bufnr;
9530 autocmd_match = save_autocmd_match;
9531#ifdef FEAT_EVAL
9532 current_SID = save_current_SID;
9533 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00009534# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009535 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009536 prof_child_exit(&wait_time);
9537# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009538#endif
9539 vim_free(fname);
9540 vim_free(sfname);
9541 --nesting; /* see matching increment above */
9542
9543 /*
9544 * When stopping to execute autocommands, restore the search patterns and
9545 * the redo buffer.
9546 */
9547 if (!autocmd_busy)
9548 {
9549 restore_search_patterns();
9550 restoreRedobuff();
9551 did_filetype = FALSE;
9552 }
9553
9554 /*
9555 * Some events don't set or reset the Changed flag.
9556 * Check if still in the same buffer!
9557 */
9558 if (curbuf == old_curbuf
9559 && (event == EVENT_BUFREADPOST
9560 || event == EVENT_BUFWRITEPOST
9561 || event == EVENT_FILEAPPENDPOST
9562 || event == EVENT_VIMLEAVE
9563 || event == EVENT_VIMLEAVEPRE))
9564 {
9565#ifdef FEAT_TITLE
9566 if (curbuf->b_changed != save_changed)
9567 need_maketitle = TRUE;
9568#endif
9569 curbuf->b_changed = save_changed;
9570 }
9571
9572 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009573
9574BYPASS_AU:
9575 /* When wiping out a buffer make sure all its buffer-local autocommands
9576 * are deleted. */
9577 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9578 aubuflocal_remove(buf);
9579
Bram Moolenaar071d4272004-06-13 20:20:40 +00009580 return retval;
9581}
9582
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009583# ifdef FEAT_EVAL
9584static char_u *old_termresponse = NULL;
9585# endif
9586
9587/*
9588 * Block triggering autocommands until unblock_autocmd() is called.
9589 * Can be used recursively, so long as it's symmetric.
9590 */
9591 void
9592block_autocmds()
9593{
9594# ifdef FEAT_EVAL
9595 /* Remember the value of v:termresponse. */
9596 if (autocmd_blocked == 0)
9597 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9598# endif
9599 ++autocmd_blocked;
9600}
9601
9602 void
9603unblock_autocmds()
9604{
9605 --autocmd_blocked;
9606
9607# ifdef FEAT_EVAL
9608 /* When v:termresponse was set while autocommands were blocked, trigger
9609 * the autocommands now. Esp. useful when executing a shell command
9610 * during startup (vimdiff). */
9611 if (autocmd_blocked == 0
9612 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9613 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9614# endif
9615}
9616
Bram Moolenaarabab85a2013-06-26 19:18:05 +02009617 int
9618is_autocmd_blocked()
9619{
9620 return autocmd_blocked != 0;
9621}
9622
Bram Moolenaar071d4272004-06-13 20:20:40 +00009623/*
9624 * Find next autocommand pattern that matches.
9625 */
9626 static void
9627auto_next_pat(apc, stop_at_last)
9628 AutoPatCmd *apc;
9629 int stop_at_last; /* stop when 'last' flag is set */
9630{
9631 AutoPat *ap;
9632 AutoCmd *cp;
9633 char_u *name;
9634 char *s;
9635
9636 vim_free(sourcing_name);
9637 sourcing_name = NULL;
9638
9639 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9640 {
9641 apc->curpat = NULL;
9642
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009643 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009644 * the group matches. For buffer-local autocommands only check the
9645 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009646 if (ap->pat != NULL && ap->cmds != NULL
9647 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9648 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009649 /* execution-condition */
9650 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009651 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
9652 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009653 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009654 {
9655 name = event_nr2name(apc->event);
9656 s = _("%s Auto commands for \"%s\"");
9657 sourcing_name = alloc((unsigned)(STRLEN(s)
9658 + STRLEN(name) + ap->patlen + 1));
9659 if (sourcing_name != NULL)
9660 {
9661 sprintf((char *)sourcing_name, s,
9662 (char *)name, (char *)ap->pat);
9663 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009664 {
9665 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009666 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009667 verbose_leave();
9668 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009669 }
9670
9671 apc->curpat = ap;
9672 apc->nextcmd = ap->cmds;
9673 /* mark last command */
9674 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9675 cp->last = FALSE;
9676 cp->last = TRUE;
9677 }
9678 line_breakcheck();
9679 if (apc->curpat != NULL) /* found a match */
9680 break;
9681 }
9682 if (stop_at_last && ap->last)
9683 break;
9684 }
9685}
9686
9687/*
9688 * Get next autocommand command.
9689 * Called by do_cmdline() to get the next line for ":if".
9690 * Returns allocated string, or NULL for end of autocommands.
9691 */
Bram Moolenaar21691f82012-12-05 19:13:18 +01009692 char_u *
Bram Moolenaar071d4272004-06-13 20:20:40 +00009693getnextac(c, cookie, indent)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009694 int c UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009695 void *cookie;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009696 int indent UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009697{
9698 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9699 char_u *retval;
9700 AutoCmd *ac;
9701
9702 /* Can be called again after returning the last line. */
9703 if (acp->curpat == NULL)
9704 return NULL;
9705
9706 /* repeat until we find an autocommand to execute */
9707 for (;;)
9708 {
9709 /* skip removed commands */
9710 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9711 if (acp->nextcmd->last)
9712 acp->nextcmd = NULL;
9713 else
9714 acp->nextcmd = acp->nextcmd->next;
9715
9716 if (acp->nextcmd != NULL)
9717 break;
9718
9719 /* at end of commands, find next pattern that matches */
9720 if (acp->curpat->last)
9721 acp->curpat = NULL;
9722 else
9723 acp->curpat = acp->curpat->next;
9724 if (acp->curpat != NULL)
9725 auto_next_pat(acp, TRUE);
9726 if (acp->curpat == NULL)
9727 return NULL;
9728 }
9729
9730 ac = acp->nextcmd;
9731
9732 if (p_verbose >= 9)
9733 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009734 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009735 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009736 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009737 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009738 }
9739 retval = vim_strsave(ac->cmd);
9740 autocmd_nested = ac->nested;
9741#ifdef FEAT_EVAL
9742 current_SID = ac->scriptID;
9743#endif
9744 if (ac->last)
9745 acp->nextcmd = NULL;
9746 else
9747 acp->nextcmd = ac->next;
9748 return retval;
9749}
9750
9751/*
9752 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009753 * To account for buffer-local autocommands, function needs to know
9754 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009755 */
9756 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009757has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009758 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009759 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009760 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009761{
9762 AutoPat *ap;
9763 char_u *fname;
9764 char_u *tail = gettail(sfname);
9765 int retval = FALSE;
9766
9767 fname = FullName_save(sfname, FALSE);
9768 if (fname == NULL)
9769 return FALSE;
9770
9771#ifdef BACKSLASH_IN_FILENAME
9772 /*
9773 * Replace all backslashes with forward slashes. This makes the
9774 * autocommand patterns portable between Unix and MS-DOS.
9775 */
9776 sfname = vim_strsave(sfname);
9777 if (sfname != NULL)
9778 forward_slash(sfname);
9779 forward_slash(fname);
9780#endif
9781
9782 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9783 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009784 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009785 ? match_file_pat(NULL, ap->reg_prog,
9786 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009787 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009788 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009789 {
9790 retval = TRUE;
9791 break;
9792 }
9793
9794 vim_free(fname);
9795#ifdef BACKSLASH_IN_FILENAME
9796 vim_free(sfname);
9797#endif
9798
9799 return retval;
9800}
9801
9802#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9803/*
9804 * Function given to ExpandGeneric() to obtain the list of autocommand group
9805 * names.
9806 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009807 char_u *
9808get_augroup_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009809 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009810 int idx;
9811{
9812 if (idx == augroups.ga_len) /* add "END" add the end */
9813 return (char_u *)"END";
9814 if (idx >= augroups.ga_len) /* end of list */
9815 return NULL;
9816 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
9817 return (char_u *)"";
9818 return AUGROUP_NAME(idx); /* return a name */
9819}
9820
9821static int include_groups = FALSE;
9822
9823 char_u *
9824set_context_in_autocmd(xp, arg, doautocmd)
9825 expand_T *xp;
9826 char_u *arg;
Bram Moolenaard812df62008-11-09 12:46:09 +00009827 int doautocmd; /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009828{
9829 char_u *p;
9830 int group;
9831
9832 /* check for a group name, skip it if present */
9833 include_groups = FALSE;
9834 p = arg;
9835 group = au_get_grouparg(&arg);
9836 if (group == AUGROUP_ERROR)
9837 return NULL;
9838 /* If there only is a group name that's what we expand. */
9839 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
9840 {
9841 arg = p;
9842 group = AUGROUP_ALL;
9843 }
9844
9845 /* skip over event name */
9846 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
9847 if (*p == ',')
9848 arg = p + 1;
9849 if (*p == NUL)
9850 {
9851 if (group == AUGROUP_ALL)
9852 include_groups = TRUE;
9853 xp->xp_context = EXPAND_EVENTS; /* expand event name */
9854 xp->xp_pattern = arg;
9855 return NULL;
9856 }
9857
9858 /* skip over pattern */
9859 arg = skipwhite(p);
9860 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
9861 arg++;
9862 if (*arg)
9863 return arg; /* expand (next) command */
9864
9865 if (doautocmd)
9866 xp->xp_context = EXPAND_FILES; /* expand file names */
9867 else
9868 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9869 return NULL;
9870}
9871
9872/*
9873 * Function given to ExpandGeneric() to obtain the list of event names.
9874 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009875 char_u *
9876get_event_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009877 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009878 int idx;
9879{
9880 if (idx < augroups.ga_len) /* First list group names, if wanted */
9881 {
9882 if (!include_groups || AUGROUP_NAME(idx) == NULL)
9883 return (char_u *)""; /* skip deleted entries */
9884 return AUGROUP_NAME(idx); /* return a name */
9885 }
9886 return (char_u *)event_names[idx - augroups.ga_len].name;
9887}
9888
9889#endif /* FEAT_CMDL_COMPL */
9890
9891/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009892 * Return TRUE if autocmd is supported.
9893 */
9894 int
9895autocmd_supported(name)
9896 char_u *name;
9897{
9898 char_u *p;
9899
9900 return (event_name2nr(name, &p) != NUM_EVENTS);
9901}
9902
9903/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00009904 * Return TRUE if an autocommand is defined for a group, event and
9905 * pattern: The group can be omitted to accept any group. "event" and "pattern"
9906 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
9907 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
9908 * Used for:
9909 * exists("#Group") or
9910 * exists("#Group#Event") or
9911 * exists("#Group#Event#pat") or
9912 * exists("#Event") or
9913 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00009914 */
9915 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00009916au_exists(arg)
9917 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009918{
Bram Moolenaar195d6352005-12-19 22:08:24 +00009919 char_u *arg_save;
9920 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009921 char_u *event_name;
9922 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00009923 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009924 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009925 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00009926 int group;
9927 int retval = FALSE;
9928
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009929 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009930 arg_save = vim_strsave(arg);
9931 if (arg_save == NULL)
9932 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009933 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00009934 if (p != NULL)
9935 *p++ = NUL;
9936
9937 /* First, look for an autocmd group name */
9938 group = au_find_group(arg_save);
9939 if (group == AUGROUP_ERROR)
9940 {
9941 /* Didn't match a group name, assume the first argument is an event. */
9942 group = AUGROUP_ALL;
9943 event_name = arg_save;
9944 }
9945 else
9946 {
9947 if (p == NULL)
9948 {
9949 /* "Group": group name is present and it's recognized */
9950 retval = TRUE;
9951 goto theend;
9952 }
9953
9954 /* Must be "Group#Event" or "Group#Event#pat". */
9955 event_name = p;
9956 p = vim_strchr(event_name, '#');
9957 if (p != NULL)
9958 *p++ = NUL; /* "Group#Event#pat" */
9959 }
9960
9961 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962
9963 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009964 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009965
9966 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009967 if (event == NUM_EVENTS)
9968 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009969
9970 /* Find the first autocommand for this event.
9971 * If there isn't any, return FALSE;
9972 * If there is one and no pattern given, return TRUE; */
9973 ap = first_autopat[(int)event];
9974 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009975 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009976
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009977 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9978 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009979 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009980 buflocal_buf = curbuf;
9981
Bram Moolenaar071d4272004-06-13 20:20:40 +00009982 /* Check if there is an autocommand with the given pattern. */
9983 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009984 /* only use a pattern when it has not been removed and has commands. */
9985 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009986 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00009987 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009988 && (pattern == NULL
9989 || (buflocal_buf == NULL
9990 ? fnamecmp(ap->pat, pattern) == 0
9991 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +00009992 {
9993 retval = TRUE;
9994 break;
9995 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009996
Bram Moolenaar195d6352005-12-19 22:08:24 +00009997theend:
9998 vim_free(arg_save);
9999 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010000}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +000010001
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010002#else /* FEAT_AUTOCMD */
10003
10004/*
10005 * Prepare for executing commands for (hidden) buffer "buf".
10006 * This is the non-autocommand version, it simply saves "curbuf" and sets
10007 * "curbuf" and "curwin" to match "buf".
10008 */
10009 void
10010aucmd_prepbuf(aco, buf)
10011 aco_save_T *aco; /* structure to save values in */
10012 buf_T *buf; /* new curbuf */
10013{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010014 aco->save_curbuf = curbuf;
10015 --curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010016 curbuf = buf;
10017 curwin->w_buffer = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010018 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010019}
10020
10021/*
10022 * Restore after executing commands for a (hidden) buffer.
10023 * This is the non-autocommand version.
10024 */
10025 void
10026aucmd_restbuf(aco)
10027 aco_save_T *aco; /* structure holding saved values */
10028{
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010029 --curbuf->b_nwindows;
10030 curbuf = aco->save_curbuf;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010031 curwin->w_buffer = curbuf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +000010032 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010033}
10034
Bram Moolenaar071d4272004-06-13 20:20:40 +000010035#endif /* FEAT_AUTOCMD */
10036
Bram Moolenaarf30e74c2006-08-16 17:35:00 +000010037
Bram Moolenaar071d4272004-06-13 20:20:40 +000010038#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
10039/*
Bram Moolenaar748bf032005-02-02 23:04:36 +000010040 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
10041 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
10042 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010043 * Used for autocommands and 'wildignore'.
10044 * Returns TRUE if there is a match, FALSE otherwise.
10045 */
10046 int
Bram Moolenaar748bf032005-02-02 23:04:36 +000010047match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010048 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +000010049 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010050 char_u *fname; /* full path of file name */
10051 char_u *sfname; /* short file name or NULL */
10052 char_u *tail; /* tail of path */
10053 int allow_dirs; /* allow matching with dir */
10054{
10055 regmatch_T regmatch;
10056 int result = FALSE;
10057#ifdef FEAT_OSFILETYPE
10058 int no_pattern = FALSE; /* TRUE if check is filetype only */
10059 char_u *type_start;
10060 char_u c;
10061 int match = FALSE;
10062#endif
10063
Bram Moolenaar71afbfe2013-03-19 16:49:16 +010010064 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010065#ifdef FEAT_OSFILETYPE
10066 if (*pattern == '<')
10067 {
10068 /* There is a filetype condition specified with this pattern.
10069 * Check the filetype matches first. If not, don't bother with the
10070 * pattern (set regprog to NULL).
10071 * Always use magic for the regexp.
10072 */
10073
10074 for (type_start = pattern + 1; (c = *pattern); pattern++)
10075 {
10076 if ((c == ';' || c == '>') && match == FALSE)
10077 {
10078 *pattern = NUL; /* Terminate the string */
Bram Moolenaar05334432011-07-20 18:29:39 +020010079 /* TODO: match with 'filetype' of buffer that "fname" comes
10080 * from. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010081 match = mch_check_filetype(fname, type_start);
10082 *pattern = c; /* Restore the terminator */
10083 type_start = pattern + 1;
10084 }
10085 if (c == '>')
10086 break;
10087 }
10088
10089 /* (c should never be NUL, but check anyway) */
10090 if (match == FALSE || c == NUL)
10091 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
10092 else if (*pattern == NUL)
10093 {
10094 regmatch.regprog = NULL; /* Vim will try to free regprog later */
10095 no_pattern = TRUE; /* Always matches - don't check pat. */
10096 }
10097 else
10098 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
10099 }
10100 else
10101#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +000010102 {
10103 if (prog != NULL)
10104 regmatch.regprog = prog;
10105 else
10106 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
10107 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010108
10109 /*
10110 * Try for a match with the pattern with:
10111 * 1. the full file name, when the pattern has a '/'.
10112 * 2. the short file name, when the pattern has a '/'.
10113 * 3. the tail of the file name, when the pattern has no '/'.
10114 */
10115 if (
10116#ifdef FEAT_OSFILETYPE
10117 /* If the check is for a filetype only and we don't care
10118 * about the path then skip all the regexp stuff.
10119 */
10120 no_pattern ||
10121#endif
10122 (regmatch.regprog != NULL
10123 && ((allow_dirs
10124 && (vim_regexec(&regmatch, fname, (colnr_T)0)
10125 || (sfname != NULL
10126 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
10127 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
10128 result = TRUE;
10129
Bram Moolenaar748bf032005-02-02 23:04:36 +000010130 if (prog == NULL)
Bram Moolenaar473de612013-06-08 18:19:48 +020010131 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010132 return result;
10133}
10134#endif
10135
10136#if defined(FEAT_WILDIGN) || defined(PROTO)
10137/*
10138 * Return TRUE if a file matches with a pattern in "list".
10139 * "list" is a comma-separated list of patterns, like 'wildignore'.
10140 * "sfname" is the short file name or NULL, "ffname" the long file name.
10141 */
10142 int
10143match_file_list(list, sfname, ffname)
10144 char_u *list;
10145 char_u *sfname;
10146 char_u *ffname;
10147{
10148 char_u buf[100];
10149 char_u *tail;
10150 char_u *regpat;
10151 char allow_dirs;
10152 int match;
10153 char_u *p;
10154
10155 tail = gettail(sfname);
10156
10157 /* try all patterns in 'wildignore' */
10158 p = list;
10159 while (*p)
10160 {
10161 copy_option_part(&p, buf, 100, ",");
10162 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
10163 if (regpat == NULL)
10164 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +000010165 match = match_file_pat(regpat, NULL, ffname, sfname,
10166 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010167 vim_free(regpat);
10168 if (match)
10169 return TRUE;
10170 }
10171 return FALSE;
10172}
10173#endif
10174
10175/*
10176 * Convert the given pattern "pat" which has shell style wildcards in it, into
10177 * a regular expression, and return the result in allocated memory. If there
10178 * is a directory path separator to be matched, then TRUE is put in
10179 * allow_dirs, otherwise FALSE is put there -- webb.
10180 * Handle backslashes before special characters, like "\*" and "\ ".
10181 *
10182 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
10183 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
10184 *
10185 * Returns NULL when out of memory.
10186 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010187 char_u *
10188file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
10189 char_u *pat;
10190 char_u *pat_end; /* first char after pattern or NULL */
10191 char *allow_dirs; /* Result passed back out in here */
Bram Moolenaar78a15312009-05-15 19:33:18 +000010192 int no_bslash UNUSED; /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010193{
10194 int size;
10195 char_u *endp;
10196 char_u *reg_pat;
10197 char_u *p;
10198 int i;
10199 int nested = 0;
10200 int add_dollar = TRUE;
10201#ifdef FEAT_OSFILETYPE
10202 int check_length = 0;
10203#endif
10204
10205 if (allow_dirs != NULL)
10206 *allow_dirs = FALSE;
10207 if (pat_end == NULL)
10208 pat_end = pat + STRLEN(pat);
10209
10210#ifdef FEAT_OSFILETYPE
10211 /* Find out how much of the string is the filetype check */
10212 if (*pat == '<')
10213 {
10214 /* Count chars until the next '>' */
10215 for (p = pat + 1; p < pat_end && *p != '>'; p++)
10216 ;
10217 if (p < pat_end)
10218 {
10219 /* Pattern is of the form <.*>.* */
10220 check_length = p - pat + 1;
10221 if (p + 1 >= pat_end)
10222 {
10223 /* The 'pattern' is a filetype check ONLY */
10224 reg_pat = (char_u *)alloc(check_length + 1);
10225 if (reg_pat != NULL)
10226 {
10227 mch_memmove(reg_pat, pat, (size_t)check_length);
10228 reg_pat[check_length] = NUL;
10229 }
10230 return reg_pat;
10231 }
10232 }
10233 /* else: there was no closing '>' - assume it was a normal pattern */
10234
10235 }
10236 pat += check_length;
10237 size = 2 + check_length;
10238#else
10239 size = 2; /* '^' at start, '$' at end */
10240#endif
10241
10242 for (p = pat; p < pat_end; p++)
10243 {
10244 switch (*p)
10245 {
10246 case '*':
10247 case '.':
10248 case ',':
10249 case '{':
10250 case '}':
10251 case '~':
10252 size += 2; /* extra backslash */
10253 break;
10254#ifdef BACKSLASH_IN_FILENAME
10255 case '\\':
10256 case '/':
10257 size += 4; /* could become "[\/]" */
10258 break;
10259#endif
10260 default:
10261 size++;
10262# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010263 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010264 {
10265 ++p;
10266 ++size;
10267 }
10268# endif
10269 break;
10270 }
10271 }
10272 reg_pat = alloc(size + 1);
10273 if (reg_pat == NULL)
10274 return NULL;
10275
10276#ifdef FEAT_OSFILETYPE
10277 /* Copy the type check in to the start. */
10278 if (check_length)
10279 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
10280 i = check_length;
10281#else
10282 i = 0;
10283#endif
10284
10285 if (pat[0] == '*')
10286 while (pat[0] == '*' && pat < pat_end - 1)
10287 pat++;
10288 else
10289 reg_pat[i++] = '^';
10290 endp = pat_end - 1;
10291 if (*endp == '*')
10292 {
10293 while (endp - pat > 0 && *endp == '*')
10294 endp--;
10295 add_dollar = FALSE;
10296 }
10297 for (p = pat; *p && nested >= 0 && p <= endp; p++)
10298 {
10299 switch (*p)
10300 {
10301 case '*':
10302 reg_pat[i++] = '.';
10303 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +000010304 while (p[1] == '*') /* "**" matches like "*" */
10305 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010306 break;
10307 case '.':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010308 case '~':
10309 reg_pat[i++] = '\\';
10310 reg_pat[i++] = *p;
10311 break;
10312 case '?':
Bram Moolenaar071d4272004-06-13 20:20:40 +000010313 reg_pat[i++] = '.';
10314 break;
10315 case '\\':
10316 if (p[1] == NUL)
10317 break;
10318#ifdef BACKSLASH_IN_FILENAME
10319 if (!no_bslash)
10320 {
10321 /* translate:
10322 * "\x" to "\\x" e.g., "dir\file"
10323 * "\*" to "\\.*" e.g., "dir\*.c"
10324 * "\?" to "\\." e.g., "dir\??.c"
10325 * "\+" to "\+" e.g., "fileX\+.c"
10326 */
10327 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
10328 && p[1] != '+')
10329 {
10330 reg_pat[i++] = '[';
10331 reg_pat[i++] = '\\';
10332 reg_pat[i++] = '/';
10333 reg_pat[i++] = ']';
10334 if (allow_dirs != NULL)
10335 *allow_dirs = TRUE;
10336 break;
10337 }
10338 }
10339#endif
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010340 /* Undo escaping from ExpandEscape():
10341 * foo\?bar -> foo?bar
10342 * foo\%bar -> foo%bar
10343 * foo\,bar -> foo,bar
10344 * foo\ bar -> foo bar
10345 * Don't unescape \, * and others that are also special in a
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010346 * regexp.
10347 * An escaped { must be unescaped since we use magic not
Bram Moolenaara946afe2013-08-02 15:22:39 +020010348 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010349 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010350 if (*++p == '?'
10351#ifdef BACKSLASH_IN_FILENAME
10352 && no_bslash
10353#endif
10354 )
10355 reg_pat[i++] = '?';
10356 else
Bram Moolenaarf4e11432013-07-03 16:53:03 +020010357 if (*p == ',' || *p == '%' || *p == '#'
Bram Moolenaara946afe2013-08-02 15:22:39 +020010358 || *p == ' ' || *p == '{' || *p == '}')
Bram Moolenaar8cd213c2010-06-01 21:57:09 +020010359 reg_pat[i++] = *p;
Bram Moolenaara946afe2013-08-02 15:22:39 +020010360 else if (*p == '\\' && p[1] == '\\' && p[2] == '{')
10361 {
10362 reg_pat[i++] = '\\';
10363 reg_pat[i++] = '{';
10364 p += 2;
10365 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010366 else
10367 {
10368 if (allow_dirs != NULL && vim_ispathsep(*p)
10369#ifdef BACKSLASH_IN_FILENAME
10370 && (!no_bslash || *p != '\\')
10371#endif
10372 )
10373 *allow_dirs = TRUE;
10374 reg_pat[i++] = '\\';
10375 reg_pat[i++] = *p;
10376 }
10377 break;
10378#ifdef BACKSLASH_IN_FILENAME
10379 case '/':
10380 reg_pat[i++] = '[';
10381 reg_pat[i++] = '\\';
10382 reg_pat[i++] = '/';
10383 reg_pat[i++] = ']';
10384 if (allow_dirs != NULL)
10385 *allow_dirs = TRUE;
10386 break;
10387#endif
10388 case '{':
10389 reg_pat[i++] = '\\';
10390 reg_pat[i++] = '(';
10391 nested++;
10392 break;
10393 case '}':
10394 reg_pat[i++] = '\\';
10395 reg_pat[i++] = ')';
10396 --nested;
10397 break;
10398 case ',':
10399 if (nested)
10400 {
10401 reg_pat[i++] = '\\';
10402 reg_pat[i++] = '|';
10403 }
10404 else
10405 reg_pat[i++] = ',';
10406 break;
10407 default:
10408# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010409 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010410 reg_pat[i++] = *p++;
10411 else
10412# endif
10413 if (allow_dirs != NULL && vim_ispathsep(*p))
10414 *allow_dirs = TRUE;
10415 reg_pat[i++] = *p;
10416 break;
10417 }
10418 }
10419 if (add_dollar)
10420 reg_pat[i++] = '$';
10421 reg_pat[i] = NUL;
10422 if (nested != 0)
10423 {
10424 if (nested < 0)
10425 EMSG(_("E219: Missing {."));
10426 else
10427 EMSG(_("E220: Missing }."));
10428 vim_free(reg_pat);
10429 reg_pat = NULL;
10430 }
10431 return reg_pat;
10432}
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010433
10434#if defined(EINTR) || defined(PROTO)
10435/*
10436 * Version of read() that retries when interrupted by EINTR (possibly
10437 * by a SIGWINCH).
10438 */
10439 long
10440read_eintr(fd, buf, bufsize)
10441 int fd;
10442 void *buf;
10443 size_t bufsize;
10444{
10445 long ret;
10446
10447 for (;;)
10448 {
10449 ret = vim_read(fd, buf, bufsize);
10450 if (ret >= 0 || errno != EINTR)
10451 break;
10452 }
10453 return ret;
10454}
10455
10456/*
10457 * Version of write() that retries when interrupted by EINTR (possibly
10458 * by a SIGWINCH).
10459 */
10460 long
10461write_eintr(fd, buf, bufsize)
10462 int fd;
10463 void *buf;
10464 size_t bufsize;
10465{
10466 long ret = 0;
10467 long wlen;
10468
10469 /* Repeat the write() so long it didn't fail, other than being interrupted
10470 * by a signal. */
10471 while (ret < (long)bufsize)
10472 {
Bram Moolenaar9c263032010-12-17 18:06:06 +010010473 wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
Bram Moolenaar540fc6f2010-12-17 16:27:16 +010010474 if (wlen < 0)
10475 {
10476 if (errno != EINTR)
10477 break;
10478 }
10479 else
10480 ret += wlen;
10481 }
10482 return ret;
10483}
10484#endif