blob: 8cf799d2bfa770fa444a53fe25af8102069e5acd [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
14#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015# include "vimio.h" /* for lseek(), must be before vim.h */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016#endif
17
18#if defined __EMX__
Bram Moolenaar362e1a32006-03-06 23:29:24 +000019# include "vimio.h" /* for mktemp(), CJW 1997-12-03 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020#endif
21
22#include "vim.h"
23
Bram Moolenaarf4888d02009-12-02 12:31:27 +000024#if defined(__TANDEM) || defined(__MINT__)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025# include <limits.h> /* for SSIZE_MAX */
26#endif
27
28#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
29# include <utime.h> /* for struct utimbuf */
30#endif
31
32#define BUFSIZE 8192 /* size of normal write buffer */
33#define SMBUFSIZE 256 /* size of emergency write buffer */
34
35#ifdef FEAT_CRYPT
Bram Moolenaar40e6a712010-05-16 22:32:54 +020036/* crypt_magic[0] is pkzip crypt, crypt_magic[1] is sha2+blowfish */
Bram Moolenaarf50a2532010-05-21 15:36:08 +020037static char *crypt_magic[] = {"VimCrypt~01!", "VimCrypt~02!"};
38static char crypt_magic_head[] = "VimCrypt~";
39# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
40static int crypt_seed_len[] = {0, 8};
Bram Moolenaar40e6a712010-05-16 22:32:54 +020041#define CRYPT_SEED_LEN_MAX 8
Bram Moolenaar071d4272004-06-13 20:20:40 +000042#endif
43
44/* Is there any system that doesn't have access()? */
Bram Moolenaar9372a112005-12-06 19:59:18 +000045#define USE_MCH_ACCESS
Bram Moolenaar071d4272004-06-13 20:20:40 +000046
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +000047#if defined(sun) && defined(S_ISCHR)
48# define OPEN_CHR_FILES
49static int is_dev_fd_file(char_u *fname);
50#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000051#ifdef FEAT_MBYTE
52static char_u *next_fenc __ARGS((char_u **pp));
53# ifdef FEAT_EVAL
54static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));
55# endif
56#endif
57#ifdef FEAT_VIMINFO
58static void check_marks_read __ARGS((void));
59#endif
60#ifdef FEAT_CRYPT
Bram Moolenaar40e6a712010-05-16 22:32:54 +020061static int get_crypt_method __ARGS((char *ptr, int len));
Bram Moolenaarf50a2532010-05-21 15:36:08 +020062static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile, int *did_ask));
Bram Moolenaar071d4272004-06-13 20:20:40 +000063#endif
64#ifdef UNIX
65static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
66#endif
Bram Moolenaar2d3f4892006-01-20 23:02:51 +000067static int set_rw_fname __ARGS((char_u *fname, char_u *sfname));
Bram Moolenaar071d4272004-06-13 20:20:40 +000068static int msg_add_fileformat __ARGS((int eol_type));
Bram Moolenaar071d4272004-06-13 20:20:40 +000069static void msg_add_eol __ARGS((void));
70static int check_mtime __ARGS((buf_T *buf, struct stat *s));
71static int time_differs __ARGS((long t1, long t2));
72#ifdef FEAT_AUTOCMD
Bram Moolenaar754b5602006-02-09 23:53:20 +000073static 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 +000074static int au_find_group __ARGS((char_u *name));
75
76# define AUGROUP_DEFAULT -1 /* default autocmd group */
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +000077# define AUGROUP_ERROR -2 /* erroneous autocmd group */
Bram Moolenaar70836c82006-02-20 21:28:49 +000078# define AUGROUP_ALL -3 /* all autocmd groups */
Bram Moolenaar071d4272004-06-13 20:20:40 +000079#endif
80
81#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
82# define HAS_BW_FLAGS
83# define FIO_LATIN1 0x01 /* convert Latin1 */
84# define FIO_UTF8 0x02 /* convert UTF-8 */
85# define FIO_UCS2 0x04 /* convert UCS-2 */
86# define FIO_UCS4 0x08 /* convert UCS-4 */
87# define FIO_UTF16 0x10 /* convert UTF-16 */
88# ifdef WIN3264
89# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
90# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
91# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
92# endif
93# ifdef MACOS_X
94# define FIO_MACROMAN 0x20 /* convert MacRoman */
95# endif
96# define FIO_ENDIAN_L 0x80 /* little endian */
97# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
98# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
99# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
100# define FIO_ALL -1 /* allow all formats */
101#endif
102
103/* When converting, a read() or write() may leave some bytes to be converted
104 * for the next call. The value is guessed... */
105#define CONV_RESTLEN 30
106
107/* We have to guess how much a sequence of bytes may expand when converting
108 * with iconv() to be able to allocate a buffer. */
109#define ICONV_MULT 8
110
111/*
112 * Structure to pass arguments from buf_write() to buf_write_bytes().
113 */
114struct bw_info
115{
116 int bw_fd; /* file descriptor */
117 char_u *bw_buf; /* buffer with data to be written */
Bram Moolenaard089d9b2007-09-30 12:02:55 +0000118 int bw_len; /* length of data */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119#ifdef HAS_BW_FLAGS
120 int bw_flags; /* FIO_ flags */
121#endif
122#ifdef FEAT_MBYTE
123 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
124 int bw_restlen; /* nr of bytes in bw_rest[] */
125 int bw_first; /* first write call */
126 char_u *bw_conv_buf; /* buffer for writing converted chars */
127 int bw_conv_buflen; /* size of bw_conv_buf */
128 int bw_conv_error; /* set for conversion error */
Bram Moolenaar32b485f2009-07-29 16:06:27 +0000129 linenr_T bw_conv_error_lnum; /* first line with error or zero */
130 linenr_T bw_start_lnum; /* line number at start of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000131# ifdef USE_ICONV
132 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
133# endif
134#endif
135};
136
137static int buf_write_bytes __ARGS((struct bw_info *ip));
138
139#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000140static linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000141static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +0000142static int need_conversion __ARGS((char_u *fenc));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143static int get_fio_flags __ARGS((char_u *ptr));
144static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
145static int make_bom __ARGS((char_u *buf, char_u *name));
146# ifdef WIN3264
147static int get_win_fio_flags __ARGS((char_u *ptr));
148# endif
149# ifdef MACOS_X
150static int get_mac_fio_flags __ARGS((char_u *ptr));
151# endif
152#endif
153static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000154#ifdef TEMPDIRNAMES
Bram Moolenaareaf03392009-11-17 11:08:52 +0000155static void vim_settempdir __ARGS((char_u *tempdir));
Bram Moolenaar4592dee2009-11-18 19:11:58 +0000156#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000157#ifdef FEAT_AUTOCMD
158static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
159#endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000160
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161 void
162filemess(buf, name, s, attr)
163 buf_T *buf;
164 char_u *name;
165 char_u *s;
166 int attr;
167{
168 int msg_scroll_save;
169
170 if (msg_silent != 0)
171 return;
172 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
173 /* If it's extremely long, truncate it. */
174 if (STRLEN(IObuff) > IOSIZE - 80)
175 IObuff[IOSIZE - 80] = NUL;
176 STRCAT(IObuff, s);
177 /*
178 * For the first message may have to start a new line.
179 * For further ones overwrite the previous one, reset msg_scroll before
180 * calling filemess().
181 */
182 msg_scroll_save = msg_scroll;
183 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
184 msg_scroll = FALSE;
185 if (!msg_scroll) /* wait a bit when overwriting an error msg */
186 check_for_delay(FALSE);
187 msg_start();
188 msg_scroll = msg_scroll_save;
189 msg_scrolled_ign = TRUE;
190 /* may truncate the message to avoid a hit-return prompt */
191 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
192 msg_clr_eos();
193 out_flush();
194 msg_scrolled_ign = FALSE;
195}
196
197/*
198 * Read lines from file "fname" into the buffer after line "from".
199 *
200 * 1. We allocate blocks with lalloc, as big as possible.
201 * 2. Each block is filled with characters from the file with a single read().
202 * 3. The lines are inserted in the buffer with ml_append().
203 *
204 * (caller must check that fname != NULL, unless READ_STDIN is used)
205 *
206 * "lines_to_skip" is the number of lines that must be skipped
207 * "lines_to_read" is the number of lines that are appended
208 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
209 *
210 * flags:
211 * READ_NEW starting to edit a new buffer
212 * READ_FILTER reading filter output
213 * READ_STDIN read from stdin instead of a file
214 * READ_BUFFER read from curbuf instead of a file (converting after reading
215 * stdin)
216 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
217 *
218 * return FAIL for failure, OK otherwise
219 */
220 int
221readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
222 char_u *fname;
223 char_u *sfname;
224 linenr_T from;
225 linenr_T lines_to_skip;
226 linenr_T lines_to_read;
227 exarg_T *eap; /* can be NULL! */
228 int flags;
229{
230 int fd = 0;
231 int newfile = (flags & READ_NEW);
232 int check_readonly;
233 int filtering = (flags & READ_FILTER);
234 int read_stdin = (flags & READ_STDIN);
235 int read_buffer = (flags & READ_BUFFER);
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000236 int set_options = newfile || read_buffer
237 || (eap != NULL && eap->read_edit);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
239 colnr_T read_buf_col = 0; /* next char to read from this line */
240 char_u c;
241 linenr_T lnum = from;
242 char_u *ptr = NULL; /* pointer into read buffer */
243 char_u *buffer = NULL; /* read buffer */
244 char_u *new_buffer = NULL; /* init to shut up gcc */
245 char_u *line_start = NULL; /* init to shut up gcc */
246 int wasempty; /* buffer was empty before reading */
247 colnr_T len;
248 long size = 0;
249 char_u *p;
250 long filesize = 0;
251 int skip_read = FALSE;
252#ifdef FEAT_CRYPT
253 char_u *cryptkey = NULL;
Bram Moolenaarf50a2532010-05-21 15:36:08 +0200254 int did_ask_for_key = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000255#endif
256 int split = 0; /* number of split lines */
257#define UNKNOWN 0x0fffffff /* file size is unknown */
258 linenr_T linecnt;
259 int error = FALSE; /* errors encountered */
260 int ff_error = EOL_UNKNOWN; /* file format with errors */
261 long linerest = 0; /* remaining chars in line */
262#ifdef UNIX
263 int perm = 0;
264 int swap_mode = -1; /* protection bits for swap file */
265#else
266 int perm;
267#endif
268 int fileformat = 0; /* end-of-line format */
269 int keep_fileformat = FALSE;
270 struct stat st;
271 int file_readonly;
272 linenr_T skip_count = 0;
273 linenr_T read_count = 0;
274 int msg_save = msg_scroll;
275 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
276 * last read was missing the eol */
277 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
278 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
279 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
280 int file_rewind = FALSE;
281#ifdef FEAT_MBYTE
282 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000283 linenr_T conv_error = 0; /* line nr with conversion error */
284 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000285 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
286 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000287 int bad_char_behavior = BAD_REPLACE;
288 /* BAD_KEEP, BAD_DROP or character to
289 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000290 char_u *tmpname = NULL; /* name of 'charconvert' output file */
291 int fio_flags = 0;
292 char_u *fenc; /* fileencoding to use */
293 int fenc_alloced; /* fenc_next is in allocated memory */
294 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
295 int advance_fenc = FALSE;
296 long real_size = 0;
297# ifdef USE_ICONV
298 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
299# ifdef FEAT_EVAL
300 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
301 'charconvert' next */
302# endif
303# endif
304 int converted = FALSE; /* TRUE if conversion done */
305 int notconverted = FALSE; /* TRUE if conversion wanted but it
306 wasn't possible */
307 char_u conv_rest[CONV_RESTLEN];
308 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
309#endif
310
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000311#ifdef FEAT_AUTOCMD
312 /* Remember the initial values of curbuf, curbuf->b_ffname and
313 * curbuf->b_fname to detect whether they are altered as a result of
314 * executing nasty autocommands. Also check if "fname" and "sfname"
315 * point to one of these values. */
316 buf_T *old_curbuf = curbuf;
317 char_u *old_b_ffname = curbuf->b_ffname;
318 char_u *old_b_fname = curbuf->b_fname;
319 int using_b_ffname = (fname == curbuf->b_ffname)
320 || (sfname == curbuf->b_ffname);
321 int using_b_fname = (fname == curbuf->b_fname)
322 || (sfname == curbuf->b_fname);
323#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000324 write_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000325
326 /*
327 * If there is no file name yet, use the one for the read file.
328 * BF_NOTEDITED is set to reflect this.
329 * Don't do this for a read from a filter.
330 * Only do this when 'cpoptions' contains the 'f' flag.
331 */
332 if (curbuf->b_ffname == NULL
333 && !filtering
334 && fname != NULL
335 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
336 && !(flags & READ_DUMMY))
337 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000338 if (set_rw_fname(fname, sfname) == FAIL)
339 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000340 }
341
Bram Moolenaardf177f62005-02-22 08:39:57 +0000342 /* After reading a file the cursor line changes but we don't want to
343 * display the line. */
344 ex_no_reprint = TRUE;
345
Bram Moolenaar55b7cf82006-09-09 12:52:42 +0000346 /* don't display the file info for another buffer now */
347 need_fileinfo = FALSE;
348
Bram Moolenaar071d4272004-06-13 20:20:40 +0000349 /*
350 * For Unix: Use the short file name whenever possible.
351 * Avoids problems with networks and when directory names are changed.
352 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
353 * another directory, which we don't detect.
354 */
355 if (sfname == NULL)
356 sfname = fname;
357#if defined(UNIX) || defined(__EMX__)
358 fname = sfname;
359#endif
360
361#ifdef FEAT_AUTOCMD
362 /*
363 * The BufReadCmd and FileReadCmd events intercept the reading process by
364 * executing the associated commands instead.
365 */
366 if (!filtering && !read_stdin && !read_buffer)
367 {
368 pos_T pos;
369
370 pos = curbuf->b_op_start;
371
372 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
373 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
374 curbuf->b_op_start.col = 0;
375
376 if (newfile)
377 {
378 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
379 FALSE, curbuf, eap))
380#ifdef FEAT_EVAL
381 return aborting() ? FAIL : OK;
382#else
383 return OK;
384#endif
385 }
386 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
387 FALSE, NULL, eap))
388#ifdef FEAT_EVAL
389 return aborting() ? FAIL : OK;
390#else
391 return OK;
392#endif
393
394 curbuf->b_op_start = pos;
395 }
396#endif
397
398 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
399 msg_scroll = FALSE; /* overwrite previous file message */
400 else
401 msg_scroll = TRUE; /* don't overwrite previous file message */
402
403 /*
404 * If the name ends in a path separator, we can't open it. Check here,
405 * because reading the file may actually work, but then creating the swap
406 * file may destroy it! Reported on MS-DOS and Win 95.
407 * If the name is too long we might crash further on, quit here.
408 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000409 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000411 p = fname + STRLEN(fname);
412 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000413 {
414 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
415 msg_end();
416 msg_scroll = msg_save;
417 return FAIL;
418 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000419 }
420
421#ifdef UNIX
422 /*
423 * On Unix it is possible to read a directory, so we have to
424 * check for it before the mch_open().
425 */
426 if (!read_stdin && !read_buffer)
427 {
428 perm = mch_getperm(fname);
429 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
430# ifdef S_ISFIFO
431 && !S_ISFIFO(perm) /* ... or fifo */
432# endif
433# ifdef S_ISSOCK
434 && !S_ISSOCK(perm) /* ... or socket */
435# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +0000436# ifdef OPEN_CHR_FILES
437 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
438 /* ... or a character special file named /dev/fd/<n> */
439# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000440 )
441 {
442 if (S_ISDIR(perm))
443 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
444 else
445 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
446 msg_end();
447 msg_scroll = msg_save;
448 return FAIL;
449 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000451# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
452 /*
453 * MS-Windows allows opening a device, but we will probably get stuck
454 * trying to read it.
455 */
456 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
457 {
Bram Moolenaar5386a122007-06-28 20:02:32 +0000458 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000459 msg_end();
460 msg_scroll = msg_save;
461 return FAIL;
462 }
463# endif
Bram Moolenaar043545e2006-10-10 16:44:07 +0000464 }
465#endif
466
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 /* set default 'fileformat' */
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000468 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000469 {
470 if (eap != NULL && eap->force_ff != 0)
471 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
472 else if (*p_ffs != NUL)
473 set_fileformat(default_fileformat(), OPT_LOCAL);
474 }
475
476 /* set or reset 'binary' */
477 if (eap != NULL && eap->force_bin != 0)
478 {
479 int oldval = curbuf->b_p_bin;
480
481 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
482 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
483 }
484
485 /*
486 * When opening a new file we take the readonly flag from the file.
487 * Default is r/w, can be set to r/o below.
488 * Don't reset it when in readonly mode
489 * Only set/reset b_p_ro when BF_CHECK_RO is set.
490 */
491 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000492 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 curbuf->b_p_ro = FALSE;
494
495 if (newfile && !read_stdin && !read_buffer)
496 {
497 /* Remember time of file.
498 * For RISCOS, also remember the filetype.
499 */
500 if (mch_stat((char *)fname, &st) >= 0)
501 {
502 buf_store_time(curbuf, &st, fname);
503 curbuf->b_mtime_read = curbuf->b_mtime;
504
505#if defined(RISCOS) && defined(FEAT_OSFILETYPE)
506 /* Read the filetype into the buffer local filetype option. */
507 mch_read_filetype(fname);
508#endif
509#ifdef UNIX
510 /*
511 * Use the protection bits of the original file for the swap file.
512 * This makes it possible for others to read the name of the
513 * edited file from the swapfile, but only if they can read the
514 * edited file.
515 * Remove the "write" and "execute" bits for group and others
516 * (they must not write the swapfile).
517 * Add the "read" and "write" bits for the user, otherwise we may
518 * not be able to write to the file ourselves.
519 * Setting the bits is done below, after creating the swap file.
520 */
521 swap_mode = (st.st_mode & 0644) | 0600;
522#endif
523#ifdef FEAT_CW_EDITOR
524 /* Get the FSSpec on MacOS
525 * TODO: Update it properly when the buffer name changes
526 */
527 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
528#endif
529#ifdef VMS
530 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000531 curbuf->b_fab_rat = st.st_fab_rat;
532 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533#endif
534 }
535 else
536 {
537 curbuf->b_mtime = 0;
538 curbuf->b_mtime_read = 0;
539 curbuf->b_orig_size = 0;
540 curbuf->b_orig_mode = 0;
541 }
542
543 /* Reset the "new file" flag. It will be set again below when the
544 * file doesn't exist. */
545 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
546 }
547
548/*
549 * for UNIX: check readonly with perm and mch_access()
550 * for RISCOS: same as Unix, otherwise file gets re-datestamped!
551 * for MSDOS and Amiga: check readonly by trying to open the file for writing
552 */
553 file_readonly = FALSE;
554 if (read_stdin)
555 {
556#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
557 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
558 setmode(0, O_BINARY);
559#endif
560 }
561 else if (!read_buffer)
562 {
563#ifdef USE_MCH_ACCESS
564 if (
565# ifdef UNIX
566 !(perm & 0222) ||
567# endif
568 mch_access((char *)fname, W_OK))
569 file_readonly = TRUE;
570 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
571#else
572 if (!newfile
573 || readonlymode
574 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
575 {
576 file_readonly = TRUE;
577 /* try to open ro */
578 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
579 }
580#endif
581 }
582
583 if (fd < 0) /* cannot open at all */
584 {
585#ifndef UNIX
586 int isdir_f;
587#endif
588 msg_scroll = msg_save;
589#ifndef UNIX
590 /*
591 * On MSDOS and Amiga we can't open a directory, check here.
592 */
593 isdir_f = (mch_isdir(fname));
594 perm = mch_getperm(fname); /* check if the file exists */
595 if (isdir_f)
596 {
597 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
598 curbuf->b_p_ro = TRUE; /* must use "w!" now */
599 }
600 else
601#endif
602 if (newfile)
603 {
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200604 if (perm < 0
605#ifdef ENOENT
606 && errno == ENOENT
607#endif
608 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 {
610 /*
611 * Set the 'new-file' flag, so that when the file has
612 * been created by someone else, a ":w" will complain.
613 */
614 curbuf->b_flags |= BF_NEW;
615
616 /* Create a swap file now, so that other Vims are warned
617 * that we are editing this file. Don't do this for a
618 * "nofile" or "nowrite" buffer type. */
619#ifdef FEAT_QUICKFIX
620 if (!bt_dontwrite(curbuf))
621#endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000622 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000623 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000624#ifdef FEAT_AUTOCMD
625 /* SwapExists autocommand may mess things up */
626 if (curbuf != old_curbuf
627 || (using_b_ffname
628 && (old_b_ffname != curbuf->b_ffname))
629 || (using_b_fname
630 && (old_b_fname != curbuf->b_fname)))
631 {
632 EMSG(_(e_auchangedbuf));
633 return FAIL;
634 }
635#endif
636 }
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000637 if (dir_of_file_exists(fname))
638 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
639 else
640 filemess(curbuf, sfname,
641 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642#ifdef FEAT_VIMINFO
643 /* Even though this is a new file, it might have been
644 * edited before and deleted. Get the old marks. */
645 check_marks_read();
646#endif
647#ifdef FEAT_MBYTE
648 if (eap != NULL && eap->force_enc != 0)
649 {
650 /* set forced 'fileencoding' */
651 fenc = enc_canonize(eap->cmd + eap->force_enc);
652 if (fenc != NULL)
653 set_string_option_direct((char_u *)"fenc", -1,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000654 fenc, OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655 vim_free(fenc);
656 }
657#endif
658#ifdef FEAT_AUTOCMD
659 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
660 FALSE, curbuf, eap);
661#endif
662 /* remember the current fileformat */
663 save_file_ff(curbuf);
664
665#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
666 if (aborting()) /* autocmds may abort script processing */
667 return FAIL;
668#endif
669 return OK; /* a new file is not an error */
670 }
671 else
672 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000673 filemess(curbuf, sfname, (char_u *)(
674# ifdef EFBIG
675 (errno == EFBIG) ? _("[File too big]") :
676# endif
Bram Moolenaar2efbc662010-05-14 18:56:38 +0200677# ifdef EOVERFLOW
678 (errno == EOVERFLOW) ? _("[File too big]") :
679# endif
Bram Moolenaar202795b2005-10-11 20:29:39 +0000680 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 curbuf->b_p_ro = TRUE; /* must use "w!" now */
682 }
683 }
684
685 return FAIL;
686 }
687
688 /*
689 * Only set the 'ro' flag for readonly files the first time they are
690 * loaded. Help files always get readonly mode
691 */
692 if ((check_readonly && file_readonly) || curbuf->b_help)
693 curbuf->b_p_ro = TRUE;
694
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000695 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000696 {
Bram Moolenaar690ffc02008-01-04 15:31:21 +0000697 /* Don't change 'eol' if reading from buffer as it will already be
698 * correctly set when reading stdin. */
699 if (!read_buffer)
700 {
701 curbuf->b_p_eol = TRUE;
702 curbuf->b_start_eol = TRUE;
703 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704#ifdef FEAT_MBYTE
705 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000706 curbuf->b_start_bomb = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707#endif
708 }
709
710 /* Create a swap file now, so that other Vims are warned that we are
711 * editing this file.
712 * Don't do this for a "nofile" or "nowrite" buffer type. */
713#ifdef FEAT_QUICKFIX
714 if (!bt_dontwrite(curbuf))
715#endif
716 {
717 check_need_swap(newfile);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000718#ifdef FEAT_AUTOCMD
719 if (!read_stdin && (curbuf != old_curbuf
720 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
721 || (using_b_fname && (old_b_fname != curbuf->b_fname))))
722 {
723 EMSG(_(e_auchangedbuf));
724 if (!read_buffer)
725 close(fd);
726 return FAIL;
727 }
728#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729#ifdef UNIX
730 /* Set swap file protection bits after creating it. */
Bram Moolenaarf061e0b2009-06-24 15:32:01 +0000731 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
732 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733 (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
734#endif
735 }
736
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000737#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738 /* If "Quit" selected at ATTENTION dialog, don't load the file */
739 if (swap_exists_action == SEA_QUIT)
740 {
741 if (!read_buffer && !read_stdin)
742 close(fd);
743 return FAIL;
744 }
745#endif
746
747 ++no_wait_return; /* don't wait for return yet */
748
749 /*
750 * Set '[ mark to the line above where the lines go (line 1 if zero).
751 */
752 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
753 curbuf->b_op_start.col = 0;
754
755#ifdef FEAT_AUTOCMD
756 if (!read_buffer)
757 {
758 int m = msg_scroll;
759 int n = msg_scrolled;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760
761 /*
762 * The file must be closed again, the autocommands may want to change
763 * the file before reading it.
764 */
765 if (!read_stdin)
766 close(fd); /* ignore errors */
767
768 /*
769 * The output from the autocommands should not overwrite anything and
770 * should not be overwritten: Set msg_scroll, restore its value if no
771 * output was done.
772 */
773 msg_scroll = TRUE;
774 if (filtering)
775 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
776 FALSE, curbuf, eap);
777 else if (read_stdin)
778 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
779 FALSE, curbuf, eap);
780 else if (newfile)
781 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
782 FALSE, curbuf, eap);
783 else
784 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
785 FALSE, NULL, eap);
786 if (msg_scrolled == n)
787 msg_scroll = m;
788
789#ifdef FEAT_EVAL
790 if (aborting()) /* autocmds may abort script processing */
791 {
792 --no_wait_return;
793 msg_scroll = msg_save;
794 curbuf->b_p_ro = TRUE; /* must use "w!" now */
795 return FAIL;
796 }
797#endif
798 /*
799 * Don't allow the autocommands to change the current buffer.
800 * Try to re-open the file.
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000801 *
802 * Don't allow the autocommands to change the buffer name either
803 * (cd for example) if it invalidates fname or sfname.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804 */
805 if (!read_stdin && (curbuf != old_curbuf
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +0000806 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
807 || (using_b_fname && (old_b_fname != curbuf->b_fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
809 {
810 --no_wait_return;
811 msg_scroll = msg_save;
812 if (fd < 0)
813 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
814 else
815 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
816 curbuf->b_p_ro = TRUE; /* must use "w!" now */
817 return FAIL;
818 }
819 }
820#endif /* FEAT_AUTOCMD */
821
822 /* Autocommands may add lines to the file, need to check if it is empty */
823 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
824
825 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
826 {
827 /*
828 * Show the user that we are busy reading the input. Sometimes this
829 * may take a while. When reading from stdin another program may
830 * still be running, don't move the cursor to the last line, unless
831 * always using the GUI.
832 */
833 if (read_stdin)
834 {
835#ifndef ALWAYS_USE_GUI
836 mch_msg(_("Vim: Reading from stdin...\n"));
837#endif
838#ifdef FEAT_GUI
839 /* Also write a message in the GUI window, if there is one. */
840 if (gui.in_use && !gui.dying && !gui.starting)
841 {
842 p = (char_u *)_("Reading from stdin...");
843 gui_write(p, (int)STRLEN(p));
844 }
845#endif
846 }
847 else if (!read_buffer)
848 filemess(curbuf, sfname, (char_u *)"", 0);
849 }
850
851 msg_scroll = FALSE; /* overwrite the file message */
852
853 /*
854 * Set linecnt now, before the "retry" caused by a wrong guess for
855 * fileformat, and after the autocommands, which may change them.
856 */
857 linecnt = curbuf->b_ml.ml_line_count;
858
859#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000860 /* "++bad=" argument. */
861 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000862 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000863 bad_char_behavior = eap->bad_char;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000864 if (set_options)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000865 curbuf->b_bad_char = eap->bad_char;
866 }
867 else
868 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000869
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000871 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 */
873 if (eap != NULL && eap->force_enc != 0)
874 {
875 fenc = enc_canonize(eap->cmd + eap->force_enc);
876 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000877 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 }
879 else if (curbuf->b_p_bin)
880 {
881 fenc = (char_u *)""; /* binary: don't convert */
882 fenc_alloced = FALSE;
883 }
884 else if (curbuf->b_help)
885 {
886 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000887 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888
889 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
890 * fails it must be latin1.
891 * Always do this when 'encoding' is "utf-8". Otherwise only do
892 * this when needed to avoid [converted] remarks all the time.
893 * It is needed when the first line contains non-ASCII characters.
894 * That is only in *.??x files. */
895 fenc = (char_u *)"latin1";
896 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000897 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000899 fc = fname[STRLEN(fname) - 1];
900 if (TOLOWER_ASC(fc) == 'x')
901 {
902 /* Read the first line (and a bit more). Immediately rewind to
903 * the start of the file. If the read() fails "len" is -1. */
904 len = vim_read(fd, firstline, 80);
905 lseek(fd, (off_t)0L, SEEK_SET);
906 for (p = firstline; p < firstline + len; ++p)
907 if (*p >= 0x80)
908 {
909 c = TRUE;
910 break;
911 }
912 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 }
914
915 if (c)
916 {
917 fenc_next = fenc;
918 fenc = (char_u *)"utf-8";
919
920 /* When the file is utf-8 but a character doesn't fit in
921 * 'encoding' don't retry. In help text editing utf-8 bytes
922 * doesn't make sense. */
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000923 if (!enc_utf8)
924 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925 }
926 fenc_alloced = FALSE;
927 }
928 else if (*p_fencs == NUL)
929 {
930 fenc = curbuf->b_p_fenc; /* use format from buffer */
931 fenc_alloced = FALSE;
932 }
933 else
934 {
935 fenc_next = p_fencs; /* try items in 'fileencodings' */
936 fenc = next_fenc(&fenc_next);
937 fenc_alloced = TRUE;
938 }
939#endif
940
941 /*
942 * Jump back here to retry reading the file in different ways.
943 * Reasons to retry:
944 * - encoding conversion failed: try another one from "fenc_next"
945 * - BOM detected and fenc was set, need to setup conversion
946 * - "fileformat" check failed: try another
947 *
948 * Variables set for special retry actions:
949 * "file_rewind" Rewind the file to start reading it again.
950 * "advance_fenc" Advance "fenc" using "fenc_next".
951 * "skip_read" Re-use already read bytes (BOM detected).
952 * "did_iconv" iconv() conversion failed, try 'charconvert'.
953 * "keep_fileformat" Don't reset "fileformat".
954 *
955 * Other status indicators:
956 * "tmpname" When != NULL did conversion with 'charconvert'.
957 * Output file has to be deleted afterwards.
958 * "iconv_fd" When != -1 did conversion with iconv().
959 */
960retry:
961
962 if (file_rewind)
963 {
964 if (read_buffer)
965 {
966 read_buf_lnum = 1;
967 read_buf_col = 0;
968 }
969 else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
970 {
971 /* Can't rewind the file, give up. */
972 error = TRUE;
973 goto failed;
974 }
975 /* Delete the previously read lines. */
976 while (lnum > from)
977 ml_delete(lnum--, FALSE);
978 file_rewind = FALSE;
979#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000980 if (set_options)
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000981 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 curbuf->b_p_bomb = FALSE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +0000983 curbuf->b_start_bomb = FALSE;
984 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000985 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986#endif
987 }
988
989 /*
990 * When retrying with another "fenc" and the first time "fileformat"
991 * will be reset.
992 */
993 if (keep_fileformat)
994 keep_fileformat = FALSE;
995 else
996 {
997 if (eap != NULL && eap->force_ff != 0)
Bram Moolenaar1c860362008-11-12 15:05:21 +0000998 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 fileformat = get_fileformat_force(curbuf, eap);
Bram Moolenaar1c860362008-11-12 15:05:21 +00001000 try_unix = try_dos = try_mac = FALSE;
1001 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 else if (curbuf->b_p_bin)
1003 fileformat = EOL_UNIX; /* binary: use Unix format */
1004 else if (*p_ffs == NUL)
1005 fileformat = get_fileformat(curbuf);/* use format from buffer */
1006 else
1007 fileformat = EOL_UNKNOWN; /* detect from file */
1008 }
1009
1010#ifdef FEAT_MBYTE
1011# ifdef USE_ICONV
1012 if (iconv_fd != (iconv_t)-1)
1013 {
1014 /* aborted conversion with iconv(), close the descriptor */
1015 iconv_close(iconv_fd);
1016 iconv_fd = (iconv_t)-1;
1017 }
1018# endif
1019
1020 if (advance_fenc)
1021 {
1022 /*
1023 * Try the next entry in 'fileencodings'.
1024 */
1025 advance_fenc = FALSE;
1026
1027 if (eap != NULL && eap->force_enc != 0)
1028 {
1029 /* Conversion given with "++cc=" wasn't possible, read
1030 * without conversion. */
1031 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001032 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 if (fenc_alloced)
1034 vim_free(fenc);
1035 fenc = (char_u *)"";
1036 fenc_alloced = FALSE;
1037 }
1038 else
1039 {
1040 if (fenc_alloced)
1041 vim_free(fenc);
1042 if (fenc_next != NULL)
1043 {
1044 fenc = next_fenc(&fenc_next);
1045 fenc_alloced = (fenc_next != NULL);
1046 }
1047 else
1048 {
1049 fenc = (char_u *)"";
1050 fenc_alloced = FALSE;
1051 }
1052 }
1053 if (tmpname != NULL)
1054 {
1055 mch_remove(tmpname); /* delete converted file */
1056 vim_free(tmpname);
1057 tmpname = NULL;
1058 }
1059 }
1060
1061 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001062 * Conversion may be required when the encoding of the file is different
1063 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 */
1065 fio_flags = 0;
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00001066 converted = need_conversion(fenc);
1067 if (converted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001068 {
1069
1070 /* "ucs-bom" means we need to check the first bytes of the file
1071 * for a BOM. */
1072 if (STRCMP(fenc, ENC_UCSBOM) == 0)
1073 fio_flags = FIO_UCSBOM;
1074
1075 /*
1076 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
1077 * done. This is handled below after read(). Prepare the
1078 * fio_flags to avoid having to parse the string each time.
1079 * Also check for Unicode to Latin1 conversion, because iconv()
1080 * appears not to handle this correctly. This works just like
1081 * conversion to UTF-8 except how the resulting character is put in
1082 * the buffer.
1083 */
1084 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
1085 fio_flags = get_fio_flags(fenc);
1086
1087# ifdef WIN3264
1088 /*
1089 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
1090 * is handled with MultiByteToWideChar().
1091 */
1092 if (fio_flags == 0)
1093 fio_flags = get_win_fio_flags(fenc);
1094# endif
1095
1096# ifdef MACOS_X
1097 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
1098 if (fio_flags == 0)
1099 fio_flags = get_mac_fio_flags(fenc);
1100# endif
1101
1102# ifdef USE_ICONV
1103 /*
1104 * Try using iconv() if we can't convert internally.
1105 */
1106 if (fio_flags == 0
1107# ifdef FEAT_EVAL
1108 && !did_iconv
1109# endif
1110 )
1111 iconv_fd = (iconv_t)my_iconv_open(
1112 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
1113# endif
1114
1115# ifdef FEAT_EVAL
1116 /*
1117 * Use the 'charconvert' expression when conversion is required
1118 * and we can't do it internally or with iconv().
1119 */
1120 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1121# ifdef USE_ICONV
1122 && iconv_fd == (iconv_t)-1
1123# endif
1124 )
1125 {
1126# ifdef USE_ICONV
1127 did_iconv = FALSE;
1128# endif
1129 /* Skip conversion when it's already done (retry for wrong
1130 * "fileformat"). */
1131 if (tmpname == NULL)
1132 {
1133 tmpname = readfile_charconvert(fname, fenc, &fd);
1134 if (tmpname == NULL)
1135 {
1136 /* Conversion failed. Try another one. */
1137 advance_fenc = TRUE;
1138 if (fd < 0)
1139 {
1140 /* Re-opening the original file failed! */
1141 EMSG(_("E202: Conversion made file unreadable!"));
1142 error = TRUE;
1143 goto failed;
1144 }
1145 goto retry;
1146 }
1147 }
1148 }
1149 else
1150# endif
1151 {
1152 if (fio_flags == 0
1153# ifdef USE_ICONV
1154 && iconv_fd == (iconv_t)-1
1155# endif
1156 )
1157 {
1158 /* Conversion wanted but we can't.
1159 * Try the next conversion in 'fileencodings' */
1160 advance_fenc = TRUE;
1161 goto retry;
1162 }
1163 }
1164 }
1165
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001166 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001168 * stdin or fixed at a specific encoding. */
1169 can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170#endif
1171
1172 if (!skip_read)
1173 {
1174 linerest = 0;
1175 filesize = 0;
1176 skip_count = lines_to_skip;
1177 read_count = lines_to_read;
1178#ifdef FEAT_MBYTE
1179 conv_restlen = 0;
1180#endif
1181 }
1182
1183 while (!error && !got_int)
1184 {
1185 /*
1186 * We allocate as much space for the file as we can get, plus
1187 * space for the old line plus room for one terminating NUL.
1188 * The amount is limited by the fact that read() only can read
1189 * upto max_unsigned characters (and other things).
1190 */
1191#if SIZEOF_INT <= 2
1192 if (linerest >= 0x7ff0)
1193 {
1194 ++split;
1195 *ptr = NL; /* split line by inserting a NL */
1196 size = 1;
1197 }
1198 else
1199#endif
1200 {
1201 if (!skip_read)
1202 {
1203#if SIZEOF_INT > 2
Bram Moolenaar311d9822007-02-27 15:48:28 +00001204# if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205 size = SSIZE_MAX; /* use max I/O size, 52K */
1206# else
1207 size = 0x10000L; /* use buffer >= 64K */
1208# endif
1209#else
1210 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1211#endif
1212
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001213 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214 {
1215 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1216 FALSE)) != NULL)
1217 break;
1218 }
1219 if (new_buffer == NULL)
1220 {
1221 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1222 error = TRUE;
1223 break;
1224 }
1225 if (linerest) /* copy characters from the previous buffer */
1226 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1227 vim_free(buffer);
1228 buffer = new_buffer;
1229 ptr = buffer + linerest;
1230 line_start = buffer;
1231
1232#ifdef FEAT_MBYTE
1233 /* May need room to translate into.
1234 * For iconv() we don't really know the required space, use a
1235 * factor ICONV_MULT.
1236 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1237 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1238 * become up to 4 bytes, size must be multiple of 2
1239 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1240 * multiple of 2
1241 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1242 * multiple of 4 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001243 real_size = (int)size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244# ifdef USE_ICONV
1245 if (iconv_fd != (iconv_t)-1)
1246 size = size / ICONV_MULT;
1247 else
1248# endif
1249 if (fio_flags & FIO_LATIN1)
1250 size = size / 2;
1251 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1252 size = (size * 2 / 3) & ~1;
1253 else if (fio_flags & FIO_UCS4)
1254 size = (size * 2 / 3) & ~3;
1255 else if (fio_flags == FIO_UCSBOM)
1256 size = size / ICONV_MULT; /* worst case */
1257# ifdef WIN3264
1258 else if (fio_flags & FIO_CODEPAGE)
1259 size = size / ICONV_MULT; /* also worst case */
1260# endif
1261# ifdef MACOS_X
1262 else if (fio_flags & FIO_MACROMAN)
1263 size = size / ICONV_MULT; /* also worst case */
1264# endif
1265#endif
1266
1267#ifdef FEAT_MBYTE
1268 if (conv_restlen > 0)
1269 {
1270 /* Insert unconverted bytes from previous line. */
1271 mch_memmove(ptr, conv_rest, conv_restlen);
1272 ptr += conv_restlen;
1273 size -= conv_restlen;
1274 }
1275#endif
1276
1277 if (read_buffer)
1278 {
1279 /*
1280 * Read bytes from curbuf. Used for converting text read
1281 * from stdin.
1282 */
1283 if (read_buf_lnum > from)
1284 size = 0;
1285 else
1286 {
1287 int n, ni;
1288 long tlen;
1289
1290 tlen = 0;
1291 for (;;)
1292 {
1293 p = ml_get(read_buf_lnum) + read_buf_col;
1294 n = (int)STRLEN(p);
1295 if ((int)tlen + n + 1 > size)
1296 {
1297 /* Filled up to "size", append partial line.
1298 * Change NL to NUL to reverse the effect done
1299 * below. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001300 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301 for (ni = 0; ni < n; ++ni)
1302 {
1303 if (p[ni] == NL)
1304 ptr[tlen++] = NUL;
1305 else
1306 ptr[tlen++] = p[ni];
1307 }
1308 read_buf_col += n;
1309 break;
1310 }
1311 else
1312 {
1313 /* Append whole line and new-line. Change NL
1314 * to NUL to reverse the effect done below. */
1315 for (ni = 0; ni < n; ++ni)
1316 {
1317 if (p[ni] == NL)
1318 ptr[tlen++] = NUL;
1319 else
1320 ptr[tlen++] = p[ni];
1321 }
1322 ptr[tlen++] = NL;
1323 read_buf_col = 0;
1324 if (++read_buf_lnum > from)
1325 {
1326 /* When the last line didn't have an
1327 * end-of-line don't add it now either. */
1328 if (!curbuf->b_p_eol)
1329 --tlen;
1330 size = tlen;
1331 break;
1332 }
1333 }
1334 }
1335 }
1336 }
1337 else
1338 {
1339 /*
1340 * Read bytes from the file.
1341 */
1342 size = vim_read(fd, ptr, size);
1343 }
1344
1345 if (size <= 0)
1346 {
1347 if (size < 0) /* read error */
1348 error = TRUE;
1349#ifdef FEAT_MBYTE
1350 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001351 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001352 /*
1353 * Reached end-of-file but some trailing bytes could
1354 * not be converted. Truncated file?
1355 */
1356
1357 /* When we did a conversion report an error. */
1358 if (fio_flags != 0
1359# ifdef USE_ICONV
1360 || iconv_fd != (iconv_t)-1
1361# endif
1362 )
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001363 {
Bram Moolenaarf453d352008-06-04 17:37:34 +00001364 if (conv_error == 0)
1365 conv_error = curbuf->b_ml.ml_line_count
1366 - linecnt + 1;
1367 }
1368 /* Remember the first linenr with an illegal byte */
1369 else if (illegal_byte == 0)
1370 illegal_byte = curbuf->b_ml.ml_line_count
1371 - linecnt + 1;
1372 if (bad_char_behavior == BAD_DROP)
1373 {
1374 *(ptr - conv_restlen) = NUL;
1375 conv_restlen = 0;
1376 }
1377 else
1378 {
1379 /* Replace the trailing bytes with the replacement
1380 * character if we were converting; if we weren't,
1381 * leave the UTF8 checking code to do it, as it
1382 * works slightly differently. */
1383 if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
1384# ifdef USE_ICONV
1385 || iconv_fd != (iconv_t)-1
1386# endif
1387 ))
1388 {
1389 while (conv_restlen > 0)
1390 {
1391 *(--ptr) = bad_char_behavior;
1392 --conv_restlen;
1393 }
1394 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001395 fio_flags = 0; /* don't convert this */
Bram Moolenaarb21e5842006-04-16 18:30:08 +00001396# ifdef USE_ICONV
1397 if (iconv_fd != (iconv_t)-1)
1398 {
1399 iconv_close(iconv_fd);
1400 iconv_fd = (iconv_t)-1;
1401 }
1402# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001403 }
1404 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001405#endif
1406 }
1407
1408#ifdef FEAT_CRYPT
1409 /*
1410 * At start of file: Check for magic number of encryption.
1411 */
1412 if (filesize == 0)
1413 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
Bram Moolenaarf50a2532010-05-21 15:36:08 +02001414 &filesize, newfile, &did_ask_for_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001415 /*
1416 * Decrypt the read bytes.
1417 */
1418 if (cryptkey != NULL && size > 0)
1419 for (p = ptr; p < ptr + size; ++p)
1420 ZDECODE(*p);
1421#endif
1422 }
1423 skip_read = FALSE;
1424
1425#ifdef FEAT_MBYTE
1426 /*
1427 * At start of file (or after crypt magic number): Check for BOM.
1428 * Also check for a BOM for other Unicode encodings, but not after
1429 * converting with 'charconvert' or when a BOM has already been
1430 * found.
1431 */
1432 if ((filesize == 0
1433# ifdef FEAT_CRYPT
Bram Moolenaar40e6a712010-05-16 22:32:54 +02001434 || (filesize == (CRYPT_MAGIC_LEN
1435 + 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 }
2136 ++lnum;
2137 if (--read_count == 0)
2138 {
2139 error = TRUE; /* break loop */
2140 line_start = ptr; /* nothing left to write */
2141 break;
2142 }
2143 }
2144 else
2145 --skip_count;
2146 line_start = ptr + 1;
2147 }
2148 }
2149 }
2150 else
2151 {
2152 --ptr;
2153 while (++ptr, --size >= 0)
2154 {
2155 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2156 continue;
2157 if (c == NUL)
2158 *ptr = NL; /* NULs are replaced by newlines! */
2159 else
2160 {
2161 if (skip_count == 0)
2162 {
2163 *ptr = NUL; /* end of line */
2164 len = (colnr_T)(ptr - line_start + 1);
2165 if (fileformat == EOL_DOS)
2166 {
2167 if (ptr[-1] == CAR) /* remove CR */
2168 {
2169 ptr[-1] = NUL;
2170 --len;
2171 }
2172 /*
2173 * Reading in Dos format, but no CR-LF found!
2174 * When 'fileformats' includes "unix", delete all
2175 * the lines read so far and start all over again.
2176 * Otherwise give an error message later.
2177 */
2178 else if (ff_error != EOL_DOS)
2179 {
2180 if ( try_unix
2181 && !read_stdin
2182 && (read_buffer
2183 || lseek(fd, (off_t)0L, SEEK_SET) == 0))
2184 {
2185 fileformat = EOL_UNIX;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002186 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002187 set_fileformat(EOL_UNIX, OPT_LOCAL);
2188 file_rewind = TRUE;
2189 keep_fileformat = TRUE;
2190 goto retry;
2191 }
2192 ff_error = EOL_DOS;
2193 }
2194 }
2195 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2196 {
2197 error = TRUE;
2198 break;
2199 }
2200 ++lnum;
2201 if (--read_count == 0)
2202 {
2203 error = TRUE; /* break loop */
2204 line_start = ptr; /* nothing left to write */
2205 break;
2206 }
2207 }
2208 else
2209 --skip_count;
2210 line_start = ptr + 1;
2211 }
2212 }
2213 }
2214 linerest = (long)(ptr - line_start);
2215 ui_breakcheck();
2216 }
2217
2218failed:
2219 /* not an error, max. number of lines reached */
2220 if (error && read_count == 0)
2221 error = FALSE;
2222
2223 /*
2224 * If we get EOF in the middle of a line, note the fact and
2225 * complete the line ourselves.
2226 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2227 */
2228 if (!error
2229 && !got_int
2230 && linerest != 0
2231 && !(!curbuf->b_p_bin
2232 && fileformat == EOL_DOS
2233 && *line_start == Ctrl_Z
2234 && ptr == line_start + 1))
2235 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002236 /* remember for when writing */
2237 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 curbuf->b_p_eol = FALSE;
2239 *ptr = NUL;
2240 if (ml_append(lnum, line_start,
2241 (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
2242 error = TRUE;
2243 else
2244 read_no_eol_lnum = ++lnum;
2245 }
2246
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002247 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002248 save_file_ff(curbuf); /* remember the current file format */
2249
2250#ifdef FEAT_CRYPT
2251 if (cryptkey != curbuf->b_p_key)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002252 free_crypt_key(cryptkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002253#endif
2254
2255#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002256 /* If editing a new file: set 'fenc' for the current buffer.
2257 * Also for ":read ++edit file". */
2258 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002259 set_string_option_direct((char_u *)"fenc", -1, fenc,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002260 OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002261 if (fenc_alloced)
2262 vim_free(fenc);
2263# ifdef USE_ICONV
2264 if (iconv_fd != (iconv_t)-1)
2265 {
2266 iconv_close(iconv_fd);
2267 iconv_fd = (iconv_t)-1;
2268 }
2269# endif
2270#endif
2271
2272 if (!read_buffer && !read_stdin)
2273 close(fd); /* errors are ignored */
Bram Moolenaarf05da212009-11-17 16:13:15 +00002274#ifdef HAVE_FD_CLOEXEC
2275 else
2276 {
2277 int fdflags = fcntl(fd, F_GETFD);
2278 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
2279 fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
2280 }
2281#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 vim_free(buffer);
2283
2284#ifdef HAVE_DUP
2285 if (read_stdin)
2286 {
2287 /* Use stderr for stdin, makes shell commands work. */
2288 close(0);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00002289 ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002290 }
2291#endif
2292
2293#ifdef FEAT_MBYTE
2294 if (tmpname != NULL)
2295 {
2296 mch_remove(tmpname); /* delete converted file */
2297 vim_free(tmpname);
2298 }
2299#endif
2300 --no_wait_return; /* may wait for return now */
2301
2302 /*
2303 * In recovery mode everything but autocommands is skipped.
2304 */
2305 if (!recoverymode)
2306 {
2307 /* need to delete the last line, which comes from the empty buffer */
2308 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2309 {
2310#ifdef FEAT_NETBEANS_INTG
2311 netbeansFireChanges = 0;
2312#endif
2313 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2314#ifdef FEAT_NETBEANS_INTG
2315 netbeansFireChanges = 1;
2316#endif
2317 --linecnt;
2318 }
2319 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2320 if (filesize == 0)
2321 linecnt = 0;
2322 if (newfile || read_buffer)
Bram Moolenaar7263a772007-05-10 17:35:54 +00002323 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002324 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar7263a772007-05-10 17:35:54 +00002325#ifdef FEAT_DIFF
2326 /* After reading the text into the buffer the diff info needs to
2327 * be updated. */
2328 diff_invalidate(curbuf);
2329#endif
2330#ifdef FEAT_FOLDING
2331 /* All folds in the window are invalid now. Mark them for update
2332 * before triggering autocommands. */
2333 foldUpdateAll(curwin);
2334#endif
2335 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002336 else if (linecnt) /* appended at least one line */
2337 appended_lines_mark(from, linecnt);
2338
Bram Moolenaar071d4272004-06-13 20:20:40 +00002339#ifndef ALWAYS_USE_GUI
2340 /*
2341 * If we were reading from the same terminal as where messages go,
2342 * the screen will have been messed up.
2343 * Switch on raw mode now and clear the screen.
2344 */
2345 if (read_stdin)
2346 {
2347 settmode(TMODE_RAW); /* set to raw mode */
2348 starttermcap();
2349 screenclear();
2350 }
2351#endif
2352
2353 if (got_int)
2354 {
2355 if (!(flags & READ_DUMMY))
2356 {
2357 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2358 if (newfile)
2359 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2360 }
2361 msg_scroll = msg_save;
2362#ifdef FEAT_VIMINFO
2363 check_marks_read();
2364#endif
2365 return OK; /* an interrupt isn't really an error */
2366 }
2367
2368 if (!filtering && !(flags & READ_DUMMY))
2369 {
2370 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2371 c = FALSE;
2372
2373#ifdef UNIX
2374# ifdef S_ISFIFO
2375 if (S_ISFIFO(perm)) /* fifo or socket */
2376 {
2377 STRCAT(IObuff, _("[fifo/socket]"));
2378 c = TRUE;
2379 }
2380# else
2381# ifdef S_IFIFO
2382 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2383 {
2384 STRCAT(IObuff, _("[fifo]"));
2385 c = TRUE;
2386 }
2387# endif
2388# ifdef S_IFSOCK
2389 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2390 {
2391 STRCAT(IObuff, _("[socket]"));
2392 c = TRUE;
2393 }
2394# endif
2395# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002396# ifdef OPEN_CHR_FILES
2397 if (S_ISCHR(perm)) /* or character special */
2398 {
2399 STRCAT(IObuff, _("[character special]"));
2400 c = TRUE;
2401 }
2402# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002403#endif
2404 if (curbuf->b_p_ro)
2405 {
2406 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2407 c = TRUE;
2408 }
2409 if (read_no_eol_lnum)
2410 {
2411 msg_add_eol();
2412 c = TRUE;
2413 }
2414 if (ff_error == EOL_DOS)
2415 {
2416 STRCAT(IObuff, _("[CR missing]"));
2417 c = TRUE;
2418 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002419 if (split)
2420 {
2421 STRCAT(IObuff, _("[long lines split]"));
2422 c = TRUE;
2423 }
2424#ifdef FEAT_MBYTE
2425 if (notconverted)
2426 {
2427 STRCAT(IObuff, _("[NOT converted]"));
2428 c = TRUE;
2429 }
2430 else if (converted)
2431 {
2432 STRCAT(IObuff, _("[converted]"));
2433 c = TRUE;
2434 }
2435#endif
2436#ifdef FEAT_CRYPT
2437 if (cryptkey != NULL)
2438 {
2439 STRCAT(IObuff, _("[crypted]"));
2440 c = TRUE;
2441 }
2442#endif
2443#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002444 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002446 sprintf((char *)IObuff + STRLEN(IObuff),
2447 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002448 c = TRUE;
2449 }
2450 else if (illegal_byte > 0)
2451 {
2452 sprintf((char *)IObuff + STRLEN(IObuff),
2453 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2454 c = TRUE;
2455 }
2456 else
2457#endif
2458 if (error)
2459 {
2460 STRCAT(IObuff, _("[READ ERRORS]"));
2461 c = TRUE;
2462 }
2463 if (msg_add_fileformat(fileformat))
2464 c = TRUE;
2465#ifdef FEAT_CRYPT
2466 if (cryptkey != NULL)
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002467 msg_add_lines(c, (long)linecnt, filesize
2468 - CRYPT_MAGIC_LEN - crypt_seed_len[use_crypt_method]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469 else
2470#endif
2471 msg_add_lines(c, (long)linecnt, filesize);
2472
2473 vim_free(keep_msg);
2474 keep_msg = NULL;
2475 msg_scrolled_ign = TRUE;
2476#ifdef ALWAYS_USE_GUI
2477 /* Don't show the message when reading stdin, it would end up in a
2478 * message box (which might be shown when exiting!) */
2479 if (read_stdin || read_buffer)
2480 p = msg_may_trunc(FALSE, IObuff);
2481 else
2482#endif
2483 p = msg_trunc_attr(IObuff, FALSE, 0);
2484 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002485 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 /* Need to repeat the message after redrawing when:
2487 * - When reading from stdin (the screen will be cleared next).
2488 * - When restart_edit is set (otherwise there will be a delay
2489 * before redrawing).
2490 * - When the screen was scrolled but there is no wait-return
2491 * prompt. */
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002492 set_keep_msg(p, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002493 msg_scrolled_ign = FALSE;
2494 }
2495
2496 /* with errors writing the file requires ":w!" */
2497 if (newfile && (error
2498#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002499 || conv_error != 0
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002500 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002501#endif
2502 ))
2503 curbuf->b_p_ro = TRUE;
2504
2505 u_clearline(); /* cannot use "U" command after adding lines */
2506
2507 /*
2508 * In Ex mode: cursor at last new line.
2509 * Otherwise: cursor at first new line.
2510 */
2511 if (exmode_active)
2512 curwin->w_cursor.lnum = from + linecnt;
2513 else
2514 curwin->w_cursor.lnum = from + 1;
2515 check_cursor_lnum();
2516 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2517
2518 /*
2519 * Set '[ and '] marks to the newly read lines.
2520 */
2521 curbuf->b_op_start.lnum = from + 1;
2522 curbuf->b_op_start.col = 0;
2523 curbuf->b_op_end.lnum = from + linecnt;
2524 curbuf->b_op_end.col = 0;
Bram Moolenaar03f48552006-02-28 23:52:23 +00002525
2526#ifdef WIN32
2527 /*
2528 * Work around a weird problem: When a file has two links (only
2529 * possible on NTFS) and we write through one link, then stat() it
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00002530 * through the other link, the timestamp information may be wrong.
Bram Moolenaar03f48552006-02-28 23:52:23 +00002531 * It's correct again after reading the file, thus reset the timestamp
2532 * here.
2533 */
2534 if (newfile && !read_stdin && !read_buffer
2535 && mch_stat((char *)fname, &st) >= 0)
2536 {
2537 buf_store_time(curbuf, &st, fname);
2538 curbuf->b_mtime_read = curbuf->b_mtime;
2539 }
2540#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002541 }
2542 msg_scroll = msg_save;
2543
2544#ifdef FEAT_VIMINFO
2545 /*
2546 * Get the marks before executing autocommands, so they can be used there.
2547 */
2548 check_marks_read();
2549#endif
2550
Bram Moolenaar071d4272004-06-13 20:20:40 +00002551 /*
2552 * Trick: We remember if the last line of the read didn't have
2553 * an eol for when writing it again. This is required for
2554 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
2555 */
2556 write_no_eol_lnum = read_no_eol_lnum;
2557
Bram Moolenaardf177f62005-02-22 08:39:57 +00002558#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00002559 if (!read_stdin && !read_buffer)
2560 {
2561 int m = msg_scroll;
2562 int n = msg_scrolled;
2563
2564 /* Save the fileformat now, otherwise the buffer will be considered
2565 * modified if the format/encoding was automatically detected. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002566 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002567 save_file_ff(curbuf);
2568
2569 /*
2570 * The output from the autocommands should not overwrite anything and
2571 * should not be overwritten: Set msg_scroll, restore its value if no
2572 * output was done.
2573 */
2574 msg_scroll = TRUE;
2575 if (filtering)
2576 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2577 FALSE, curbuf, eap);
2578 else if (newfile)
2579 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2580 FALSE, curbuf, eap);
2581 else
2582 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2583 FALSE, NULL, eap);
2584 if (msg_scrolled == n)
2585 msg_scroll = m;
2586#ifdef FEAT_EVAL
2587 if (aborting()) /* autocmds may abort script processing */
2588 return FAIL;
2589#endif
2590 }
2591#endif
2592
2593 if (recoverymode && error)
2594 return FAIL;
2595 return OK;
2596}
2597
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002598#ifdef OPEN_CHR_FILES
2599/*
2600 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2601 * which is the name of files used for process substitution output by
2602 * some shells on some operating systems, e.g., bash on SunOS.
2603 * Do not accept "/dev/fd/[012]", opening these may hang Vim.
2604 */
2605 static int
2606is_dev_fd_file(fname)
2607 char_u *fname;
2608{
2609 return (STRNCMP(fname, "/dev/fd/", 8) == 0
2610 && VIM_ISDIGIT(fname[8])
2611 && *skipdigits(fname + 9) == NUL
2612 && (fname[9] != NUL
2613 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
2614}
2615#endif
2616
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002617#ifdef FEAT_MBYTE
2618
2619/*
2620 * From the current line count and characters read after that, estimate the
2621 * line number where we are now.
2622 * Used for error messages that include a line number.
2623 */
2624 static linenr_T
2625readfile_linenr(linecnt, p, endp)
2626 linenr_T linecnt; /* line count before reading more bytes */
2627 char_u *p; /* start of more bytes read */
2628 char_u *endp; /* end of more bytes read */
2629{
2630 char_u *s;
2631 linenr_T lnum;
2632
2633 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2634 for (s = p; s < endp; ++s)
2635 if (*s == '\n')
2636 ++lnum;
2637 return lnum;
2638}
2639#endif
2640
Bram Moolenaar071d4272004-06-13 20:20:40 +00002641/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002642 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2643 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002644 * Returns OK or FAIL.
2645 */
2646 int
2647prep_exarg(eap, buf)
2648 exarg_T *eap;
2649 buf_T *buf;
2650{
2651 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2652#ifdef FEAT_MBYTE
2653 + STRLEN(buf->b_p_fenc)
2654#endif
2655 + 15));
2656 if (eap->cmd == NULL)
2657 return FAIL;
2658
2659#ifdef FEAT_MBYTE
2660 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2661 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
Bram Moolenaar195d6352005-12-19 22:08:24 +00002662 eap->bad_char = buf->b_bad_char;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002663#else
2664 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2665#endif
2666 eap->force_ff = 7;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002667
2668 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002669 eap->read_edit = FALSE;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002670 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671 return OK;
2672}
2673
2674#ifdef FEAT_MBYTE
2675/*
2676 * Find next fileencoding to use from 'fileencodings'.
2677 * "pp" points to fenc_next. It's advanced to the next item.
2678 * When there are no more items, an empty string is returned and *pp is set to
2679 * NULL.
2680 * When *pp is not set to NULL, the result is in allocated memory.
2681 */
2682 static char_u *
2683next_fenc(pp)
2684 char_u **pp;
2685{
2686 char_u *p;
2687 char_u *r;
2688
2689 if (**pp == NUL)
2690 {
2691 *pp = NULL;
2692 return (char_u *)"";
2693 }
2694 p = vim_strchr(*pp, ',');
2695 if (p == NULL)
2696 {
2697 r = enc_canonize(*pp);
2698 *pp += STRLEN(*pp);
2699 }
2700 else
2701 {
2702 r = vim_strnsave(*pp, (int)(p - *pp));
2703 *pp = p + 1;
2704 if (r != NULL)
2705 {
2706 p = enc_canonize(r);
2707 vim_free(r);
2708 r = p;
2709 }
2710 }
2711 if (r == NULL) /* out of memory */
2712 {
2713 r = (char_u *)"";
2714 *pp = NULL;
2715 }
2716 return r;
2717}
2718
2719# ifdef FEAT_EVAL
2720/*
2721 * Convert a file with the 'charconvert' expression.
2722 * This closes the file which is to be read, converts it and opens the
2723 * resulting file for reading.
2724 * Returns name of the resulting converted file (the caller should delete it
2725 * after reading it).
2726 * Returns NULL if the conversion failed ("*fdp" is not set) .
2727 */
2728 static char_u *
2729readfile_charconvert(fname, fenc, fdp)
2730 char_u *fname; /* name of input file */
2731 char_u *fenc; /* converted from */
2732 int *fdp; /* in/out: file descriptor of file */
2733{
2734 char_u *tmpname;
2735 char_u *errmsg = NULL;
2736
2737 tmpname = vim_tempname('r');
2738 if (tmpname == NULL)
2739 errmsg = (char_u *)_("Can't find temp file for conversion");
2740 else
2741 {
2742 close(*fdp); /* close the input file, ignore errors */
2743 *fdp = -1;
2744 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2745 fname, tmpname) == FAIL)
2746 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2747 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2748 O_RDONLY | O_EXTRA, 0)) < 0)
2749 errmsg = (char_u *)_("can't read output of 'charconvert'");
2750 }
2751
2752 if (errmsg != NULL)
2753 {
2754 /* Don't use emsg(), it breaks mappings, the retry with
2755 * another type of conversion might still work. */
2756 MSG(errmsg);
2757 if (tmpname != NULL)
2758 {
2759 mch_remove(tmpname); /* delete converted file */
2760 vim_free(tmpname);
2761 tmpname = NULL;
2762 }
2763 }
2764
2765 /* If the input file is closed, open it (caller should check for error). */
2766 if (*fdp < 0)
2767 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2768
2769 return tmpname;
2770}
2771# endif
2772
2773#endif
2774
2775#ifdef FEAT_VIMINFO
2776/*
2777 * Read marks for the current buffer from the viminfo file, when we support
2778 * buffer marks and the buffer has a name.
2779 */
2780 static void
2781check_marks_read()
2782{
2783 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2784 && curbuf->b_ffname != NULL)
Bram Moolenaard812df62008-11-09 12:46:09 +00002785 read_viminfo(NULL, VIF_WANT_MARKS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002786
2787 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2788 * the ' parameter after opening a buffer. */
2789 curbuf->b_marks_read = TRUE;
2790}
2791#endif
2792
2793#ifdef FEAT_CRYPT
2794/*
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002795 * Get the crypt method used for a file from "ptr[len]", the magic text at the
2796 * start of the file.
2797 * Returns -1 when no encryption used.
2798 */
2799 static int
2800get_crypt_method(ptr, len)
2801 char *ptr;
2802 int len;
2803{
2804 int i;
2805
2806 for (i = 0; i < (int)(sizeof(crypt_magic) / sizeof(crypt_magic[0])); i++)
2807 {
2808 if (len < (CRYPT_MAGIC_LEN + crypt_seed_len[i]))
2809 continue;
2810 if (memcmp(ptr, crypt_magic[i], CRYPT_MAGIC_LEN) == 0)
2811 return i;
2812 }
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002813
2814 i = STRLEN(crypt_magic_head);
2815 if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0)
2816 EMSG(_("E821: File is encrypted with unknown method"));
2817
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002818 return -1;
2819}
2820
2821/*
2822 * Check for magic number used for encryption. Applies to the current buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002823 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2824 * *filesizep are updated.
2825 * Return the (new) encryption key, NULL for no encryption.
2826 */
2827 static char_u *
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002828check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002829 char_u *cryptkey; /* previous encryption key or NULL */
2830 char_u *ptr; /* pointer to read bytes */
2831 long *sizep; /* length of read bytes */
2832 long *filesizep; /* nr of bytes used from file */
2833 int newfile; /* editing a new buffer */
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002834 int *did_ask; /* flag: whether already asked for key */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002835{
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002836 int method = get_crypt_method((char *)ptr, *sizep);
2837
2838 if (method >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002839 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002840 curbuf->b_p_cm = method;
2841 use_crypt_method = method;
2842 if (method > 0)
2843 (void)blowfish_self_test();
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002844 if (cryptkey == NULL && !*did_ask)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845 {
2846 if (*curbuf->b_p_key)
2847 cryptkey = curbuf->b_p_key;
2848 else
2849 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002850 /* When newfile is TRUE, store the typed key in the 'key'
2851 * option and don't free it. bf needs hash of the key saved.
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002852 * Don't ask for the key again when first time Enter was hit.
2853 * Happens when retrying to detect encoding. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854 cryptkey = get_crypt_key(newfile, FALSE);
Bram Moolenaarf50a2532010-05-21 15:36:08 +02002855 *did_ask = TRUE;
2856
Bram Moolenaar071d4272004-06-13 20:20:40 +00002857 /* check if empty key entered */
2858 if (cryptkey != NULL && *cryptkey == NUL)
2859 {
2860 if (cryptkey != curbuf->b_p_key)
2861 vim_free(cryptkey);
2862 cryptkey = NULL;
2863 }
2864 }
2865 }
2866
2867 if (cryptkey != NULL)
2868 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002869 int seed_len = crypt_seed_len[method];
2870
2871 if (method == 0)
2872 crypt_init_keys(cryptkey);
2873 else
2874 {
2875 bf_key_init(cryptkey);
2876 bf_ofb_init(ptr + CRYPT_MAGIC_LEN, seed_len);
2877 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878
2879 /* Remove magic number from the text */
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002880 *filesizep += CRYPT_MAGIC_LEN + seed_len;
2881 *sizep -= CRYPT_MAGIC_LEN + seed_len;
2882 mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN + seed_len, (size_t)*sizep);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002883 }
2884 }
Bram Moolenaar40e6a712010-05-16 22:32:54 +02002885 /* When starting to edit a new file which does not have encryption, clear
2886 * the 'key' option, except when starting up (called with -x argument) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002887 else if (newfile && *curbuf->b_p_key && !starting)
2888 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2889
2890 return cryptkey;
2891}
2892#endif
2893
2894#ifdef UNIX
2895 static void
2896set_file_time(fname, atime, mtime)
2897 char_u *fname;
2898 time_t atime; /* access time */
2899 time_t mtime; /* modification time */
2900{
2901# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
2902 struct utimbuf buf;
2903
2904 buf.actime = atime;
2905 buf.modtime = mtime;
2906 (void)utime((char *)fname, &buf);
2907# else
2908# if defined(HAVE_UTIMES)
2909 struct timeval tvp[2];
2910
2911 tvp[0].tv_sec = atime;
2912 tvp[0].tv_usec = 0;
2913 tvp[1].tv_sec = mtime;
2914 tvp[1].tv_usec = 0;
2915# ifdef NeXT
2916 (void)utimes((char *)fname, tvp);
2917# else
2918 (void)utimes((char *)fname, (const struct timeval *)&tvp);
2919# endif
2920# endif
2921# endif
2922}
2923#endif /* UNIX */
2924
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002925#if defined(VMS) && !defined(MIN)
2926/* Older DECC compiler for VAX doesn't define MIN() */
2927# define MIN(a, b) ((a) < (b) ? (a) : (b))
2928#endif
2929
Bram Moolenaar071d4272004-06-13 20:20:40 +00002930/*
Bram Moolenaar5386a122007-06-28 20:02:32 +00002931 * Return TRUE if a file appears to be read-only from the file permissions.
2932 */
2933 int
2934check_file_readonly(fname, perm)
2935 char_u *fname; /* full path to file */
2936 int perm; /* known permissions on file */
2937{
2938#ifndef USE_MCH_ACCESS
2939 int fd = 0;
2940#endif
2941
2942 return (
2943#ifdef USE_MCH_ACCESS
2944# ifdef UNIX
2945 (perm & 0222) == 0 ||
2946# endif
2947 mch_access((char *)fname, W_OK)
2948#else
2949 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
2950 ? TRUE : (close(fd), FALSE)
2951#endif
2952 );
2953}
2954
2955
2956/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00002957 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00002958 *
2959 * We do our own buffering here because fwrite() is so slow.
2960 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00002961 * If "forceit" is true, we don't care for errors when attempting backups.
2962 * In case of an error everything possible is done to restore the original
Bram Moolenaare37d50a2008-08-06 17:06:04 +00002963 * file. But when "forceit" is TRUE, we risk losing it.
Bram Moolenaar292ad192005-12-11 21:29:51 +00002964 *
2965 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
2966 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002967 *
2968 * This function must NOT use NameBuff (because it's called by autowrite()).
2969 *
2970 * return FAIL for failure, OK otherwise
2971 */
2972 int
2973buf_write(buf, fname, sfname, start, end, eap, append, forceit,
2974 reset_changed, filtering)
2975 buf_T *buf;
2976 char_u *fname;
2977 char_u *sfname;
2978 linenr_T start, end;
2979 exarg_T *eap; /* for forced 'ff' and 'fenc', can be
2980 NULL! */
Bram Moolenaar292ad192005-12-11 21:29:51 +00002981 int append; /* append to the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982 int forceit;
2983 int reset_changed;
2984 int filtering;
2985{
2986 int fd;
2987 char_u *backup = NULL;
2988 int backup_copy = FALSE; /* copy the original file? */
2989 int dobackup;
2990 char_u *ffname;
2991 char_u *wfname = NULL; /* name of file to write to */
2992 char_u *s;
2993 char_u *ptr;
2994 char_u c;
2995 int len;
2996 linenr_T lnum;
2997 long nchars;
2998 char_u *errmsg = NULL;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00002999 int errmsg_allocated = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000 char_u *errnum = NULL;
3001 char_u *buffer;
3002 char_u smallbuf[SMBUFSIZE];
3003 char_u *backup_ext;
3004 int bufsize;
3005 long perm; /* file permissions */
3006 int retval = OK;
3007 int newfile = FALSE; /* TRUE if file doesn't exist yet */
3008 int msg_save = msg_scroll;
3009 int overwriting; /* TRUE if writing over original */
3010 int no_eol = FALSE; /* no end-of-line written */
3011 int device = FALSE; /* writing to a device */
3012 struct stat st_old;
3013 int prev_got_int = got_int;
3014 int file_readonly = FALSE; /* overwritten file is read-only */
3015 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
3016#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
3017 int made_writable = FALSE; /* 'w' bit has been set */
3018#endif
3019 /* writing everything */
3020 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
3021#ifdef FEAT_AUTOCMD
3022 linenr_T old_line_count = buf->b_ml.ml_line_count;
3023#endif
3024 int attr;
3025 int fileformat;
3026 int write_bin;
3027 struct bw_info write_info; /* info for buf_write_bytes() */
3028#ifdef FEAT_MBYTE
3029 int converted = FALSE;
3030 int notconverted = FALSE;
3031 char_u *fenc; /* effective 'fileencoding' */
3032 char_u *fenc_tofree = NULL; /* allocated "fenc" */
3033#endif
3034#ifdef HAS_BW_FLAGS
3035 int wb_flags = 0;
3036#endif
3037#ifdef HAVE_ACL
3038 vim_acl_T acl = NULL; /* ACL copied from original file to
3039 backup or new file */
3040#endif
3041
3042 if (fname == NULL || *fname == NUL) /* safety check */
3043 return FAIL;
Bram Moolenaar70d60e92009-12-31 13:53:33 +00003044 if (buf->b_ml.ml_mfp == NULL)
3045 {
3046 /* This can happen during startup when there is a stray "w" in the
3047 * vimrc file. */
3048 EMSG(_(e_emptybuf));
3049 return FAIL;
3050 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003051
3052 /*
3053 * Disallow writing from .exrc and .vimrc in current directory for
3054 * security reasons.
3055 */
3056 if (check_secure())
3057 return FAIL;
3058
3059 /* Avoid a crash for a long name. */
3060 if (STRLEN(fname) >= MAXPATHL)
3061 {
3062 EMSG(_(e_longname));
3063 return FAIL;
3064 }
3065
3066#ifdef FEAT_MBYTE
3067 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
3068 write_info.bw_conv_buf = NULL;
3069 write_info.bw_conv_error = FALSE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00003070 write_info.bw_conv_error_lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003071 write_info.bw_restlen = 0;
3072# ifdef USE_ICONV
3073 write_info.bw_iconv_fd = (iconv_t)-1;
3074# endif
3075#endif
3076
Bram Moolenaardf177f62005-02-22 08:39:57 +00003077 /* After writing a file changedtick changes but we don't want to display
3078 * the line. */
3079 ex_no_reprint = TRUE;
3080
Bram Moolenaar071d4272004-06-13 20:20:40 +00003081 /*
3082 * If there is no file name yet, use the one for the written file.
3083 * BF_NOTEDITED is set to reflect this (in case the write fails).
3084 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00003085 * Don't do this when appending.
3086 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003088 if (buf->b_ffname == NULL
3089 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00003090 && whole
3091 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00003092#ifdef FEAT_QUICKFIX
3093 && !bt_nofile(buf)
3094#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003095 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00003096 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003097 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
3098 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003099 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00003101 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003102 }
3103
3104 if (sfname == NULL)
3105 sfname = fname;
3106 /*
3107 * For Unix: Use the short file name whenever possible.
3108 * Avoids problems with networks and when directory names are changed.
3109 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
3110 * another directory, which we don't detect
3111 */
3112 ffname = fname; /* remember full fname */
3113#ifdef UNIX
3114 fname = sfname;
3115#endif
3116
3117 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
3118 overwriting = TRUE;
3119 else
3120 overwriting = FALSE;
3121
3122 if (exiting)
3123 settmode(TMODE_COOK); /* when exiting allow typahead now */
3124
3125 ++no_wait_return; /* don't wait for return yet */
3126
3127 /*
3128 * Set '[ and '] marks to the lines to be written.
3129 */
3130 buf->b_op_start.lnum = start;
3131 buf->b_op_start.col = 0;
3132 buf->b_op_end.lnum = end;
3133 buf->b_op_end.col = 0;
3134
3135#ifdef FEAT_AUTOCMD
3136 {
3137 aco_save_T aco;
3138 int buf_ffname = FALSE;
3139 int buf_sfname = FALSE;
3140 int buf_fname_f = FALSE;
3141 int buf_fname_s = FALSE;
3142 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003143 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003144 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145
3146 /*
3147 * Apply PRE aucocommands.
3148 * Set curbuf to the buffer to be written.
3149 * Careful: The autocommands may call buf_write() recursively!
3150 */
3151 if (ffname == buf->b_ffname)
3152 buf_ffname = TRUE;
3153 if (sfname == buf->b_sfname)
3154 buf_sfname = TRUE;
3155 if (fname == buf->b_ffname)
3156 buf_fname_f = TRUE;
3157 if (fname == buf->b_sfname)
3158 buf_fname_s = TRUE;
3159
3160 /* set curwin/curbuf to buf and save a few things */
3161 aucmd_prepbuf(&aco, buf);
3162
3163 if (append)
3164 {
3165 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
3166 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003167 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003168#ifdef FEAT_QUICKFIX
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003169 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003170 nofile_err = TRUE;
3171 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003172#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003173 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003174 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003175 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003176 }
3177 else if (filtering)
3178 {
3179 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
3180 NULL, sfname, FALSE, curbuf, eap);
3181 }
3182 else if (reset_changed && whole)
3183 {
3184 if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
3185 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003186 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003187#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003188 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003189 nofile_err = TRUE;
3190 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003191#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003192 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003194 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003195 }
3196 else
3197 {
3198 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
3199 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003200 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003201#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003202 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003203 nofile_err = TRUE;
3204 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003205#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003206 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003207 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003208 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209 }
3210
3211 /* restore curwin/curbuf and a few other things */
3212 aucmd_restbuf(&aco);
3213
3214 /*
3215 * In three situations we return here and don't write the file:
3216 * 1. the autocommands deleted or unloaded the buffer.
3217 * 2. The autocommands abort script processing.
3218 * 3. If one of the "Cmd" autocommands was executed.
3219 */
3220 if (!buf_valid(buf))
3221 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003222 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar1e015462005-09-25 22:16:38 +00003223 || did_cmd || nofile_err
3224#ifdef FEAT_EVAL
3225 || aborting()
3226#endif
3227 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228 {
3229 --no_wait_return;
3230 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003231 if (nofile_err)
3232 EMSG(_("E676: No matching autocommands for acwrite buffer"));
3233
Bram Moolenaar1e015462005-09-25 22:16:38 +00003234 if (nofile_err
3235#ifdef FEAT_EVAL
3236 || aborting()
3237#endif
3238 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003239 /* An aborting error, interrupt or exception in the
3240 * autocommands. */
3241 return FAIL;
3242 if (did_cmd)
3243 {
3244 if (buf == NULL)
3245 /* The buffer was deleted. We assume it was written
3246 * (can't retry anyway). */
3247 return OK;
3248 if (overwriting)
3249 {
3250 /* Assume the buffer was written, update the timestamp. */
3251 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00003252 if (append)
3253 buf->b_flags &= ~BF_NEW;
3254 else
3255 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003256 }
Bram Moolenaar292ad192005-12-11 21:29:51 +00003257 if (reset_changed && buf->b_changed && !append
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003258 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003259 /* Buffer still changed, the autocommands didn't work
3260 * properly. */
3261 return FAIL;
3262 return OK;
3263 }
3264#ifdef FEAT_EVAL
3265 if (!aborting())
3266#endif
3267 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
3268 return FAIL;
3269 }
3270
3271 /*
3272 * The autocommands may have changed the number of lines in the file.
3273 * When writing the whole file, adjust the end.
3274 * When writing part of the file, assume that the autocommands only
3275 * changed the number of lines that are to be written (tricky!).
3276 */
3277 if (buf->b_ml.ml_line_count != old_line_count)
3278 {
3279 if (whole) /* write all */
3280 end = buf->b_ml.ml_line_count;
3281 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
3282 end += buf->b_ml.ml_line_count - old_line_count;
3283 else /* less lines */
3284 {
3285 end -= old_line_count - buf->b_ml.ml_line_count;
3286 if (end < start)
3287 {
3288 --no_wait_return;
3289 msg_scroll = msg_save;
3290 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
3291 return FAIL;
3292 }
3293 }
3294 }
3295
3296 /*
3297 * The autocommands may have changed the name of the buffer, which may
3298 * be kept in fname, ffname and sfname.
3299 */
3300 if (buf_ffname)
3301 ffname = buf->b_ffname;
3302 if (buf_sfname)
3303 sfname = buf->b_sfname;
3304 if (buf_fname_f)
3305 fname = buf->b_ffname;
3306 if (buf_fname_s)
3307 fname = buf->b_sfname;
3308 }
3309#endif
3310
3311#ifdef FEAT_NETBEANS_INTG
3312 if (usingNetbeans && isNetbeansBuffer(buf))
3313 {
3314 if (whole)
3315 {
3316 /*
3317 * b_changed can be 0 after an undo, but we still need to write
3318 * the buffer to NetBeans.
3319 */
3320 if (buf->b_changed || isNetbeansModified(buf))
3321 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00003322 --no_wait_return; /* may wait for return now */
3323 msg_scroll = msg_save;
3324 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003325 return retval;
3326 }
3327 else
3328 {
3329 errnum = (char_u *)"E656: ";
Bram Moolenaared0e7452008-06-27 19:17:34 +00003330 errmsg = (char_u *)_("NetBeans disallows writes of unmodified buffers");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003331 buffer = NULL;
3332 goto fail;
3333 }
3334 }
3335 else
3336 {
3337 errnum = (char_u *)"E657: ";
3338 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
3339 buffer = NULL;
3340 goto fail;
3341 }
3342 }
3343#endif
3344
3345 if (shortmess(SHM_OVER) && !exiting)
3346 msg_scroll = FALSE; /* overwrite previous file message */
3347 else
3348 msg_scroll = TRUE; /* don't overwrite previous file message */
3349 if (!filtering)
3350 filemess(buf,
3351#ifndef UNIX
3352 sfname,
3353#else
3354 fname,
3355#endif
3356 (char_u *)"", 0); /* show that we are busy */
3357 msg_scroll = FALSE; /* always overwrite the file message now */
3358
3359 buffer = alloc(BUFSIZE);
3360 if (buffer == NULL) /* can't allocate big buffer, use small
3361 * one (to be able to write when out of
3362 * memory) */
3363 {
3364 buffer = smallbuf;
3365 bufsize = SMBUFSIZE;
3366 }
3367 else
3368 bufsize = BUFSIZE;
3369
3370 /*
3371 * Get information about original file (if there is one).
3372 */
3373#if defined(UNIX) && !defined(ARCHIE)
Bram Moolenaar6f192452007-11-08 19:49:02 +00003374 st_old.st_dev = 0;
3375 st_old.st_ino = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 perm = -1;
3377 if (mch_stat((char *)fname, &st_old) < 0)
3378 newfile = TRUE;
3379 else
3380 {
3381 perm = st_old.st_mode;
3382 if (!S_ISREG(st_old.st_mode)) /* not a file */
3383 {
3384 if (S_ISDIR(st_old.st_mode))
3385 {
3386 errnum = (char_u *)"E502: ";
3387 errmsg = (char_u *)_("is a directory");
3388 goto fail;
3389 }
3390 if (mch_nodetype(fname) != NODE_WRITABLE)
3391 {
3392 errnum = (char_u *)"E503: ";
3393 errmsg = (char_u *)_("is not a file or writable device");
3394 goto fail;
3395 }
3396 /* It's a device of some kind (or a fifo) which we can write to
3397 * but for which we can't make a backup. */
3398 device = TRUE;
3399 newfile = TRUE;
3400 perm = -1;
3401 }
3402 }
3403#else /* !UNIX */
3404 /*
3405 * Check for a writable device name.
3406 */
3407 c = mch_nodetype(fname);
3408 if (c == NODE_OTHER)
3409 {
3410 errnum = (char_u *)"E503: ";
3411 errmsg = (char_u *)_("is not a file or writable device");
3412 goto fail;
3413 }
3414 if (c == NODE_WRITABLE)
3415 {
Bram Moolenaar043545e2006-10-10 16:44:07 +00003416# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
3417 /* MS-Windows allows opening a device, but we will probably get stuck
3418 * trying to write to it. */
3419 if (!p_odev)
3420 {
3421 errnum = (char_u *)"E796: ";
3422 errmsg = (char_u *)_("writing to device disabled with 'opendevice' option");
3423 goto fail;
3424 }
3425# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003426 device = TRUE;
3427 newfile = TRUE;
3428 perm = -1;
3429 }
3430 else
3431 {
3432 perm = mch_getperm(fname);
3433 if (perm < 0)
3434 newfile = TRUE;
3435 else if (mch_isdir(fname))
3436 {
3437 errnum = (char_u *)"E502: ";
3438 errmsg = (char_u *)_("is a directory");
3439 goto fail;
3440 }
3441 if (overwriting)
3442 (void)mch_stat((char *)fname, &st_old);
3443 }
3444#endif /* !UNIX */
3445
3446 if (!device && !newfile)
3447 {
3448 /*
3449 * Check if the file is really writable (when renaming the file to
3450 * make a backup we won't discover it later).
3451 */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003452 file_readonly = check_file_readonly(fname, (int)perm);
3453
Bram Moolenaar071d4272004-06-13 20:20:40 +00003454 if (!forceit && file_readonly)
3455 {
3456 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3457 {
3458 errnum = (char_u *)"E504: ";
3459 errmsg = (char_u *)_(err_readonly);
3460 }
3461 else
3462 {
3463 errnum = (char_u *)"E505: ";
3464 errmsg = (char_u *)_("is read-only (add ! to override)");
3465 }
3466 goto fail;
3467 }
3468
3469 /*
3470 * Check if the timestamp hasn't changed since reading the file.
3471 */
3472 if (overwriting)
3473 {
3474 retval = check_mtime(buf, &st_old);
3475 if (retval == FAIL)
3476 goto fail;
3477 }
3478 }
3479
3480#ifdef HAVE_ACL
3481 /*
3482 * For systems that support ACL: get the ACL from the original file.
3483 */
3484 if (!newfile)
3485 acl = mch_get_acl(fname);
3486#endif
3487
3488 /*
3489 * If 'backupskip' is not empty, don't make a backup for some files.
3490 */
3491 dobackup = (p_wb || p_bk || *p_pm != NUL);
3492#ifdef FEAT_WILDIGN
3493 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3494 dobackup = FALSE;
3495#endif
3496
3497 /*
3498 * Save the value of got_int and reset it. We don't want a previous
3499 * interruption cancel writing, only hitting CTRL-C while writing should
3500 * abort it.
3501 */
3502 prev_got_int = got_int;
3503 got_int = FALSE;
3504
3505 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3506 buf->b_saving = TRUE;
3507
3508 /*
3509 * If we are not appending or filtering, the file exists, and the
3510 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3511 * When 'patchmode' is set also make a backup when appending.
3512 *
3513 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3514 * off. This helps when editing large files on almost-full disks.
3515 */
3516 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3517 {
3518#if defined(UNIX) || defined(WIN32)
3519 struct stat st;
3520#endif
3521
3522 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3523 backup_copy = TRUE;
3524#if defined(UNIX) || defined(WIN32)
3525 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3526 {
3527 int i;
3528
3529# ifdef UNIX
3530 /*
3531 * Don't rename the file when:
3532 * - it's a hard link
3533 * - it's a symbolic link
3534 * - we don't have write permission in the directory
3535 * - we can't set the owner/group of the new file
3536 */
3537 if (st_old.st_nlink > 1
3538 || mch_lstat((char *)fname, &st) < 0
3539 || st.st_dev != st_old.st_dev
Bram Moolenaara5792f52005-11-23 21:25:05 +00003540 || st.st_ino != st_old.st_ino
3541# ifndef HAVE_FCHOWN
3542 || st.st_uid != st_old.st_uid
3543 || st.st_gid != st_old.st_gid
3544# endif
3545 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003546 backup_copy = TRUE;
3547 else
Bram Moolenaar03f48552006-02-28 23:52:23 +00003548# else
3549# ifdef WIN32
3550 /* On NTFS file systems hard links are possible. */
3551 if (mch_is_linked(fname))
3552 backup_copy = TRUE;
3553 else
3554# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003555# endif
3556 {
3557 /*
3558 * Check if we can create a file and set the owner/group to
3559 * the ones from the original file.
3560 * First find a file name that doesn't exist yet (use some
3561 * arbitrary numbers).
3562 */
3563 STRCPY(IObuff, fname);
3564 for (i = 4913; ; i += 123)
3565 {
3566 sprintf((char *)gettail(IObuff), "%d", i);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003567 if (mch_lstat((char *)IObuff, &st) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003568 break;
3569 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00003570 fd = mch_open((char *)IObuff,
3571 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003572 if (fd < 0) /* can't write in directory */
3573 backup_copy = TRUE;
3574 else
3575 {
3576# ifdef UNIX
Bram Moolenaara5792f52005-11-23 21:25:05 +00003577# ifdef HAVE_FCHOWN
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00003578 ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003579# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003580 if (mch_stat((char *)IObuff, &st) < 0
3581 || st.st_uid != st_old.st_uid
3582 || st.st_gid != st_old.st_gid
Bram Moolenaar78a15312009-05-15 19:33:18 +00003583 || (long)st.st_mode != perm)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003584 backup_copy = TRUE;
3585# endif
Bram Moolenaar98358622005-11-28 22:58:23 +00003586 /* Close the file before removing it, on MS-Windows we
3587 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003588 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003589 mch_remove(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003590 }
3591 }
3592 }
3593
3594# ifdef UNIX
3595 /*
3596 * Break symlinks and/or hardlinks if we've been asked to.
3597 */
3598 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3599 {
3600 int lstat_res;
3601
3602 lstat_res = mch_lstat((char *)fname, &st);
3603
3604 /* Symlinks. */
3605 if ((bkc_flags & BKC_BREAKSYMLINK)
3606 && lstat_res == 0
3607 && st.st_ino != st_old.st_ino)
3608 backup_copy = FALSE;
3609
3610 /* Hardlinks. */
3611 if ((bkc_flags & BKC_BREAKHARDLINK)
3612 && st_old.st_nlink > 1
3613 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3614 backup_copy = FALSE;
3615 }
3616#endif
3617
3618#endif
3619
3620 /* make sure we have a valid backup extension to use */
3621 if (*p_bex == NUL)
3622 {
3623#ifdef RISCOS
3624 backup_ext = (char_u *)"/bak";
3625#else
3626 backup_ext = (char_u *)".bak";
3627#endif
3628 }
3629 else
3630 backup_ext = p_bex;
3631
3632 if (backup_copy
3633 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3634 {
3635 int bfd;
3636 char_u *copybuf, *wp;
3637 int some_error = FALSE;
3638 struct stat st_new;
3639 char_u *dirp;
3640 char_u *rootname;
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003641#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003642 int did_set_shortname;
3643#endif
3644
3645 copybuf = alloc(BUFSIZE + 1);
3646 if (copybuf == NULL)
3647 {
3648 some_error = TRUE; /* out of memory */
3649 goto nobackup;
3650 }
3651
3652 /*
3653 * Try to make the backup in each directory in the 'bdir' option.
3654 *
3655 * Unix semantics has it, that we may have a writable file,
3656 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3657 * - the directory is not writable,
3658 * - the file may be a symbolic link,
3659 * - the file may belong to another user/group, etc.
3660 *
3661 * For these reasons, the existing writable file must be truncated
3662 * and reused. Creation of a backup COPY will be attempted.
3663 */
3664 dirp = p_bdir;
3665 while (*dirp)
3666 {
3667#ifdef UNIX
3668 st_new.st_ino = 0;
3669 st_new.st_dev = 0;
3670 st_new.st_gid = 0;
3671#endif
3672
3673 /*
3674 * Isolate one directory name, using an entry in 'bdir'.
3675 */
3676 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3677 rootname = get_file_in_dir(fname, copybuf);
3678 if (rootname == NULL)
3679 {
3680 some_error = TRUE; /* out of memory */
3681 goto nobackup;
3682 }
3683
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003684#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003685 did_set_shortname = FALSE;
3686#endif
3687
3688 /*
3689 * May try twice if 'shortname' not set.
3690 */
3691 for (;;)
3692 {
3693 /*
3694 * Make backup file name.
3695 */
3696 backup = buf_modname(
3697#ifdef SHORT_FNAME
3698 TRUE,
3699#else
3700 (buf->b_p_sn || buf->b_shortname),
3701#endif
3702 rootname, backup_ext, FALSE);
3703 if (backup == NULL)
3704 {
3705 vim_free(rootname);
3706 some_error = TRUE; /* out of memory */
3707 goto nobackup;
3708 }
3709
3710 /*
3711 * Check if backup file already exists.
3712 */
3713 if (mch_stat((char *)backup, &st_new) >= 0)
3714 {
3715#ifdef UNIX
3716 /*
3717 * Check if backup file is same as original file.
3718 * May happen when modname() gave the same file back.
3719 * E.g. silly link, or file name-length reached.
3720 * If we don't check here, we either ruin the file
3721 * when copying or erase it after writing. jw.
3722 */
3723 if (st_new.st_dev == st_old.st_dev
3724 && st_new.st_ino == st_old.st_ino)
3725 {
3726 vim_free(backup);
3727 backup = NULL; /* no backup file to delete */
3728# ifndef SHORT_FNAME
3729 /*
3730 * may try again with 'shortname' set
3731 */
3732 if (!(buf->b_shortname || buf->b_p_sn))
3733 {
3734 buf->b_shortname = TRUE;
3735 did_set_shortname = TRUE;
3736 continue;
3737 }
3738 /* setting shortname didn't help */
3739 if (did_set_shortname)
3740 buf->b_shortname = FALSE;
3741# endif
3742 break;
3743 }
3744#endif
3745
3746 /*
3747 * If we are not going to keep the backup file, don't
3748 * delete an existing one, try to use another name.
3749 * Change one character, just before the extension.
3750 */
3751 if (!p_bk)
3752 {
3753 wp = backup + STRLEN(backup) - 1
3754 - STRLEN(backup_ext);
3755 if (wp < backup) /* empty file name ??? */
3756 wp = backup;
3757 *wp = 'z';
3758 while (*wp > 'a'
3759 && mch_stat((char *)backup, &st_new) >= 0)
3760 --*wp;
3761 /* They all exist??? Must be something wrong. */
3762 if (*wp == 'a')
3763 {
3764 vim_free(backup);
3765 backup = NULL;
3766 }
3767 }
3768 }
3769 break;
3770 }
3771 vim_free(rootname);
3772
3773 /*
3774 * Try to create the backup file
3775 */
3776 if (backup != NULL)
3777 {
3778 /* remove old backup, if present */
3779 mch_remove(backup);
3780 /* Open with O_EXCL to avoid the file being created while
3781 * we were sleeping (symlink hacker attack?) */
3782 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00003783 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
3784 perm & 0777);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003785 if (bfd < 0)
3786 {
3787 vim_free(backup);
3788 backup = NULL;
3789 }
3790 else
3791 {
3792 /* set file protection same as original file, but
3793 * strip s-bit */
3794 (void)mch_setperm(backup, perm & 0777);
3795
3796#ifdef UNIX
3797 /*
3798 * Try to set the group of the backup same as the
3799 * original file. If this fails, set the protection
3800 * bits for the group same as the protection bits for
3801 * others.
3802 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003803 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00003804# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003805 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003806# endif
3807 )
3808 mch_setperm(backup,
3809 (perm & 0707) | ((perm & 07) << 3));
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00003810# ifdef HAVE_SELINUX
3811 mch_copy_sec(fname, backup);
3812# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813#endif
3814
3815 /*
3816 * copy the file.
3817 */
3818 write_info.bw_fd = bfd;
3819 write_info.bw_buf = copybuf;
3820#ifdef HAS_BW_FLAGS
3821 write_info.bw_flags = FIO_NOCONVERT;
3822#endif
3823 while ((write_info.bw_len = vim_read(fd, copybuf,
3824 BUFSIZE)) > 0)
3825 {
3826 if (buf_write_bytes(&write_info) == FAIL)
3827 {
3828 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3829 break;
3830 }
3831 ui_breakcheck();
3832 if (got_int)
3833 {
3834 errmsg = (char_u *)_(e_interr);
3835 break;
3836 }
3837 }
3838
3839 if (close(bfd) < 0 && errmsg == NULL)
3840 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3841 if (write_info.bw_len < 0)
3842 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3843#ifdef UNIX
3844 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3845#endif
3846#ifdef HAVE_ACL
3847 mch_set_acl(backup, acl);
3848#endif
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00003849#ifdef HAVE_SELINUX
3850 mch_copy_sec(fname, backup);
3851#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003852 break;
3853 }
3854 }
3855 }
3856 nobackup:
3857 close(fd); /* ignore errors for closing read file */
3858 vim_free(copybuf);
3859
3860 if (backup == NULL && errmsg == NULL)
3861 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3862 /* ignore errors when forceit is TRUE */
3863 if ((some_error || errmsg != NULL) && !forceit)
3864 {
3865 retval = FAIL;
3866 goto fail;
3867 }
3868 errmsg = NULL;
3869 }
3870 else
3871 {
3872 char_u *dirp;
3873 char_u *p;
3874 char_u *rootname;
3875
3876 /*
3877 * Make a backup by renaming the original file.
3878 */
3879 /*
3880 * If 'cpoptions' includes the "W" flag, we don't want to
3881 * overwrite a read-only file. But rename may be possible
3882 * anyway, thus we need an extra check here.
3883 */
3884 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3885 {
3886 errnum = (char_u *)"E504: ";
3887 errmsg = (char_u *)_(err_readonly);
3888 goto fail;
3889 }
3890
3891 /*
3892 *
3893 * Form the backup file name - change path/fo.o.h to
3894 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3895 * that works is used.
3896 */
3897 dirp = p_bdir;
3898 while (*dirp)
3899 {
3900 /*
3901 * Isolate one directory name and make the backup file name.
3902 */
3903 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3904 rootname = get_file_in_dir(fname, IObuff);
3905 if (rootname == NULL)
3906 backup = NULL;
3907 else
3908 {
3909 backup = buf_modname(
3910#ifdef SHORT_FNAME
3911 TRUE,
3912#else
3913 (buf->b_p_sn || buf->b_shortname),
3914#endif
3915 rootname, backup_ext, FALSE);
3916 vim_free(rootname);
3917 }
3918
3919 if (backup != NULL)
3920 {
3921 /*
3922 * If we are not going to keep the backup file, don't
3923 * delete an existing one, try to use another name.
3924 * Change one character, just before the extension.
3925 */
3926 if (!p_bk && mch_getperm(backup) >= 0)
3927 {
3928 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3929 if (p < backup) /* empty file name ??? */
3930 p = backup;
3931 *p = 'z';
3932 while (*p > 'a' && mch_getperm(backup) >= 0)
3933 --*p;
3934 /* They all exist??? Must be something wrong! */
3935 if (*p == 'a')
3936 {
3937 vim_free(backup);
3938 backup = NULL;
3939 }
3940 }
3941 }
3942 if (backup != NULL)
3943 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003944 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00003945 * Delete any existing backup and move the current version
3946 * to the backup. For safety, we don't remove the backup
3947 * until the write has finished successfully. And if the
3948 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003949 */
3950 /*
3951 * If the renaming of the original file to the backup file
3952 * works, quit here.
3953 */
3954 if (vim_rename(fname, backup) == 0)
3955 break;
3956
3957 vim_free(backup); /* don't do the rename below */
3958 backup = NULL;
3959 }
3960 }
3961 if (backup == NULL && !forceit)
3962 {
3963 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3964 goto fail;
3965 }
3966 }
3967 }
3968
3969#if defined(UNIX) && !defined(ARCHIE)
3970 /* When using ":w!" and the file was read-only: make it writable */
3971 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3972 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3973 {
3974 perm |= 0200;
3975 (void)mch_setperm(fname, perm);
3976 made_writable = TRUE;
3977 }
3978#endif
3979
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003980 /* When using ":w!" and writing to the current file, 'readonly' makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003981 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
3982 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003983 {
3984 buf->b_p_ro = FALSE;
3985#ifdef FEAT_TITLE
3986 need_maketitle = TRUE; /* set window title later */
3987#endif
3988#ifdef FEAT_WINDOWS
3989 status_redraw_all(); /* redraw status lines later */
3990#endif
3991 }
3992
3993 if (end > buf->b_ml.ml_line_count)
3994 end = buf->b_ml.ml_line_count;
3995 if (buf->b_ml.ml_flags & ML_EMPTY)
3996 start = end + 1;
3997
3998 /*
3999 * If the original file is being overwritten, there is a small chance that
4000 * we crash in the middle of writing. Therefore the file is preserved now.
4001 * This makes all block numbers positive so that recovery does not need
4002 * the original file.
4003 * Don't do this if there is a backup file and we are exiting.
4004 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004005 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00004006 && !(exiting && backup != NULL))
4007 {
4008 ml_preserve(buf, FALSE);
4009 if (got_int)
4010 {
4011 errmsg = (char_u *)_(e_interr);
4012 goto restore_backup;
4013 }
4014 }
4015
4016#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4017 /*
4018 * Before risking to lose the original file verify if there's
4019 * a resource fork to preserve, and if cannot be done warn
4020 * the users. This happens when overwriting without backups.
4021 */
4022 if (backup == NULL && overwriting && !append)
4023 if (mch_has_resource_fork(fname))
4024 {
4025 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
4026 goto restore_backup;
4027 }
4028#endif
4029
4030#ifdef VMS
4031 vms_remove_version(fname); /* remove version */
4032#endif
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00004033 /* Default: write the file directly. May write to a temp file for
Bram Moolenaar071d4272004-06-13 20:20:40 +00004034 * multi-byte conversion. */
4035 wfname = fname;
4036
4037#ifdef FEAT_MBYTE
4038 /* Check for forced 'fileencoding' from "++opt=val" argument. */
4039 if (eap != NULL && eap->force_enc != 0)
4040 {
4041 fenc = eap->cmd + eap->force_enc;
4042 fenc = enc_canonize(fenc);
4043 fenc_tofree = fenc;
4044 }
4045 else
4046 fenc = buf->b_p_fenc;
4047
4048 /*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004049 * Check if the file needs to be converted.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004050 */
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00004051 converted = need_conversion(fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004052
4053 /*
4054 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
4055 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
4056 * Prepare the flags for it and allocate bw_conv_buf when needed.
4057 */
4058 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
4059 {
4060 wb_flags = get_fio_flags(fenc);
4061 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
4062 {
4063 /* Need to allocate a buffer to translate into. */
4064 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
4065 write_info.bw_conv_buflen = bufsize * 2;
4066 else /* FIO_UCS4 */
4067 write_info.bw_conv_buflen = bufsize * 4;
4068 write_info.bw_conv_buf
4069 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4070 if (write_info.bw_conv_buf == NULL)
4071 end = 0;
4072 }
4073 }
4074
4075# ifdef WIN3264
4076 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
4077 {
4078 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
4079 write_info.bw_conv_buflen = bufsize * 4;
4080 write_info.bw_conv_buf
4081 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4082 if (write_info.bw_conv_buf == NULL)
4083 end = 0;
4084 }
4085# endif
4086
4087# ifdef MACOS_X
4088 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
4089 {
4090 write_info.bw_conv_buflen = bufsize * 3;
4091 write_info.bw_conv_buf
4092 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4093 if (write_info.bw_conv_buf == NULL)
4094 end = 0;
4095 }
4096# endif
4097
4098# if defined(FEAT_EVAL) || defined(USE_ICONV)
4099 if (converted && wb_flags == 0)
4100 {
4101# ifdef USE_ICONV
4102 /*
4103 * Use iconv() conversion when conversion is needed and it's not done
4104 * internally.
4105 */
4106 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
4107 enc_utf8 ? (char_u *)"utf-8" : p_enc);
4108 if (write_info.bw_iconv_fd != (iconv_t)-1)
4109 {
4110 /* We're going to use iconv(), allocate a buffer to convert in. */
4111 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
4112 write_info.bw_conv_buf
4113 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
4114 if (write_info.bw_conv_buf == NULL)
4115 end = 0;
4116 write_info.bw_first = TRUE;
4117 }
4118# ifdef FEAT_EVAL
4119 else
4120# endif
4121# endif
4122
4123# ifdef FEAT_EVAL
4124 /*
4125 * When the file needs to be converted with 'charconvert' after
4126 * writing, write to a temp file instead and let the conversion
4127 * overwrite the original file.
4128 */
4129 if (*p_ccv != NUL)
4130 {
4131 wfname = vim_tempname('w');
4132 if (wfname == NULL) /* Can't write without a tempfile! */
4133 {
4134 errmsg = (char_u *)_("E214: Can't find temp file for writing");
4135 goto restore_backup;
4136 }
4137 }
4138# endif
4139 }
4140# endif
4141 if (converted && wb_flags == 0
4142# ifdef USE_ICONV
4143 && write_info.bw_iconv_fd == (iconv_t)-1
4144# endif
4145# ifdef FEAT_EVAL
4146 && wfname == fname
4147# endif
4148 )
4149 {
4150 if (!forceit)
4151 {
4152 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
4153 goto restore_backup;
4154 }
4155 notconverted = TRUE;
4156 }
4157#endif
4158
4159 /*
4160 * Open the file "wfname" for writing.
4161 * We may try to open the file twice: If we can't write to the
4162 * file and forceit is TRUE we delete the existing file and try to create
4163 * a new one. If this still fails we may have lost the original file!
4164 * (this may happen when the user reached his quotum for number of files).
4165 * Appending will fail if the file does not exist and forceit is FALSE.
4166 */
4167 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
4168 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
4169 : (O_CREAT | O_TRUNC))
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004170 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171 {
4172 /*
4173 * A forced write will try to create a new file if the old one is
4174 * still readonly. This may also happen when the directory is
4175 * read-only. In that case the mch_remove() will fail.
4176 */
4177 if (errmsg == NULL)
4178 {
4179#ifdef UNIX
4180 struct stat st;
4181
4182 /* Don't delete the file when it's a hard or symbolic link. */
4183 if ((!newfile && st_old.st_nlink > 1)
4184 || (mch_lstat((char *)fname, &st) == 0
4185 && (st.st_dev != st_old.st_dev
4186 || st.st_ino != st_old.st_ino)))
4187 errmsg = (char_u *)_("E166: Can't open linked file for writing");
4188 else
4189#endif
4190 {
4191 errmsg = (char_u *)_("E212: Can't open file for writing");
4192 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
4193 && perm >= 0)
4194 {
4195#ifdef UNIX
4196 /* we write to the file, thus it should be marked
4197 writable after all */
4198 if (!(perm & 0200))
4199 made_writable = TRUE;
4200 perm |= 0200;
4201 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
4202 perm &= 0777;
4203#endif
4204 if (!append) /* don't remove when appending */
4205 mch_remove(wfname);
4206 continue;
4207 }
4208 }
4209 }
4210
4211restore_backup:
4212 {
4213 struct stat st;
4214
4215 /*
4216 * If we failed to open the file, we don't need a backup. Throw it
4217 * away. If we moved or removed the original file try to put the
4218 * backup in its place.
4219 */
4220 if (backup != NULL && wfname == fname)
4221 {
4222 if (backup_copy)
4223 {
4224 /*
4225 * There is a small chance that we removed the original,
4226 * try to move the copy in its place.
4227 * This may not work if the vim_rename() fails.
4228 * In that case we leave the copy around.
4229 */
4230 /* If file does not exist, put the copy in its place */
4231 if (mch_stat((char *)fname, &st) < 0)
4232 vim_rename(backup, fname);
4233 /* if original file does exist throw away the copy */
4234 if (mch_stat((char *)fname, &st) >= 0)
4235 mch_remove(backup);
4236 }
4237 else
4238 {
4239 /* try to put the original file back */
4240 vim_rename(backup, fname);
4241 }
4242 }
4243
4244 /* if original file no longer exists give an extra warning */
4245 if (!newfile && mch_stat((char *)fname, &st) < 0)
4246 end = 0;
4247 }
4248
4249#ifdef FEAT_MBYTE
4250 if (wfname != fname)
4251 vim_free(wfname);
4252#endif
4253 goto fail;
4254 }
4255 errmsg = NULL;
4256
4257#if defined(MACOS_CLASSIC) || defined(WIN3264)
4258 /* TODO: Is it need for MACOS_X? (Dany) */
4259 /*
4260 * On macintosh copy the original files attributes (i.e. the backup)
Bram Moolenaar7263a772007-05-10 17:35:54 +00004261 * This is done in order to preserve the resource fork and the
4262 * Finder attribute (label, comments, custom icons, file creator)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004263 */
4264 if (backup != NULL && overwriting && !append)
4265 {
4266 if (backup_copy)
4267 (void)mch_copy_file_attribute(wfname, backup);
4268 else
4269 (void)mch_copy_file_attribute(backup, wfname);
4270 }
4271
4272 if (!overwriting && !append)
4273 {
4274 if (buf->b_ffname != NULL)
4275 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
Bram Moolenaar7263a772007-05-10 17:35:54 +00004276 /* Should copy resource fork */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277 }
4278#endif
4279
4280 write_info.bw_fd = fd;
4281
4282#ifdef FEAT_CRYPT
4283 if (*buf->b_p_key && !filtering)
4284 {
Bram Moolenaar40e6a712010-05-16 22:32:54 +02004285 char_u header[CRYPT_MAGIC_LEN + CRYPT_SEED_LEN_MAX + 2];
4286 int seed_len = crypt_seed_len[buf->b_p_cm];
4287
4288 use_crypt_method = buf->b_p_cm; /* select pkzip or blowfish */
4289
4290 memset(header, 0, sizeof(header));
4291 vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method],
4292 CRYPT_MAGIC_LEN);
4293
4294 if (buf->b_p_cm == 0)
4295 crypt_init_keys(buf->b_p_key);
4296 else
4297 {
4298 /* Using blowfish, add seed. */
4299 sha2_seed(header + CRYPT_MAGIC_LEN, seed_len); /* create iv */
4300 bf_ofb_init(header + CRYPT_MAGIC_LEN, seed_len);
4301 bf_key_init(buf->b_p_key);
4302 }
4303
4304 /* Write magic number, so that Vim knows that this file is
4305 * encrypted when reading it again. This also undergoes utf-8 to
4306 * ucs-2/4 conversion when needed. */
4307 write_info.bw_buf = (char_u *)header;
4308 write_info.bw_len = CRYPT_MAGIC_LEN + seed_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309 write_info.bw_flags = FIO_NOCONVERT;
4310 if (buf_write_bytes(&write_info) == FAIL)
4311 end = 0;
4312 wb_flags |= FIO_ENCRYPTED;
4313 }
4314#endif
4315
4316 write_info.bw_buf = buffer;
4317 nchars = 0;
4318
4319 /* use "++bin", "++nobin" or 'binary' */
4320 if (eap != NULL && eap->force_bin != 0)
4321 write_bin = (eap->force_bin == FORCE_BIN);
4322 else
4323 write_bin = buf->b_p_bin;
4324
4325#ifdef FEAT_MBYTE
4326 /*
4327 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004328 * Skip it when appending and the file already existed, the BOM only makes
4329 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004330 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004331 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 {
4333 write_info.bw_len = make_bom(buffer, fenc);
4334 if (write_info.bw_len > 0)
4335 {
4336 /* don't convert, do encryption */
4337 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4338 if (buf_write_bytes(&write_info) == FAIL)
4339 end = 0;
4340 else
4341 nchars += write_info.bw_len;
4342 }
4343 }
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004344 write_info.bw_start_lnum = start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345#endif
4346
4347 write_info.bw_len = bufsize;
4348#ifdef HAS_BW_FLAGS
4349 write_info.bw_flags = wb_flags;
4350#endif
4351 fileformat = get_fileformat_force(buf, eap);
4352 s = buffer;
4353 len = 0;
4354 for (lnum = start; lnum <= end; ++lnum)
4355 {
4356 /*
4357 * The next while loop is done once for each character written.
4358 * Keep it fast!
4359 */
4360 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
4361 while ((c = *++ptr) != NUL)
4362 {
4363 if (c == NL)
4364 *s = NUL; /* replace newlines with NULs */
4365 else if (c == CAR && fileformat == EOL_MAC)
4366 *s = NL; /* Mac: replace CRs with NLs */
4367 else
4368 *s = c;
4369 ++s;
4370 if (++len != bufsize)
4371 continue;
4372 if (buf_write_bytes(&write_info) == FAIL)
4373 {
4374 end = 0; /* write error: break loop */
4375 break;
4376 }
4377 nchars += bufsize;
4378 s = buffer;
4379 len = 0;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004380#ifdef FEAT_MBYTE
4381 write_info.bw_start_lnum = lnum;
4382#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004383 }
4384 /* write failed or last line has no EOL: stop here */
4385 if (end == 0
4386 || (lnum == end
4387 && write_bin
4388 && (lnum == write_no_eol_lnum
4389 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
4390 {
4391 ++lnum; /* written the line, count it */
4392 no_eol = TRUE;
4393 break;
4394 }
4395 if (fileformat == EOL_UNIX)
4396 *s++ = NL;
4397 else
4398 {
4399 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4400 if (fileformat == EOL_DOS) /* write CR-NL */
4401 {
4402 if (++len == bufsize)
4403 {
4404 if (buf_write_bytes(&write_info) == FAIL)
4405 {
4406 end = 0; /* write error: break loop */
4407 break;
4408 }
4409 nchars += bufsize;
4410 s = buffer;
4411 len = 0;
4412 }
4413 *s++ = NL;
4414 }
4415 }
4416 if (++len == bufsize && end)
4417 {
4418 if (buf_write_bytes(&write_info) == FAIL)
4419 {
4420 end = 0; /* write error: break loop */
4421 break;
4422 }
4423 nchars += bufsize;
4424 s = buffer;
4425 len = 0;
4426
4427 ui_breakcheck();
4428 if (got_int)
4429 {
4430 end = 0; /* Interrupted, break loop */
4431 break;
4432 }
4433 }
4434#ifdef VMS
4435 /*
4436 * On VMS there is a problem: newlines get added when writing blocks
4437 * at a time. Fix it by writing a line at a time.
4438 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004439 * Explanation: VAX/DECC RTL insists that records in some RMS
4440 * structures end with a newline (carriage return) character, and if
4441 * they don't it adds one.
4442 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004443 */
Bram Moolenaarb52e2602007-10-29 21:38:54 +00004444 if (buf->b_fab_rfm == FAB$C_VFC
4445 || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004447 int b2write;
4448
4449 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4450 ? MIN(4096, bufsize)
4451 : MIN(buf->b_fab_mrs, bufsize));
4452
4453 b2write = len;
4454 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004456 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4457 if (buf_write_bytes(&write_info) == FAIL)
4458 {
4459 end = 0;
4460 break;
4461 }
4462 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004463 }
4464 write_info.bw_len = bufsize;
4465 nchars += len;
4466 s = buffer;
4467 len = 0;
4468 }
4469#endif
4470 }
4471 if (len > 0 && end > 0)
4472 {
4473 write_info.bw_len = len;
4474 if (buf_write_bytes(&write_info) == FAIL)
4475 end = 0; /* write error */
4476 nchars += len;
4477 }
4478
4479#if defined(UNIX) && defined(HAVE_FSYNC)
4480 /* On many journalling file systems there is a bug that causes both the
4481 * original and the backup file to be lost when halting the system right
4482 * after writing the file. That's because only the meta-data is
4483 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004484 * been written to disk and we don't lose it.
4485 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004486 * (could be a pipe).
4487 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
4488 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004489 {
4490 errmsg = (char_u *)_("E667: Fsync failed");
4491 end = 0;
4492 }
4493#endif
4494
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00004495#ifdef HAVE_SELINUX
4496 /* Probably need to set the security context. */
4497 if (!backup_copy)
4498 mch_copy_sec(backup, wfname);
4499#endif
4500
Bram Moolenaara5792f52005-11-23 21:25:05 +00004501#ifdef UNIX
4502 /* When creating a new file, set its owner/group to that of the original
4503 * file. Get the new device and inode number. */
4504 if (backup != NULL && !backup_copy)
4505 {
4506# ifdef HAVE_FCHOWN
4507 struct stat st;
4508
4509 /* don't change the owner when it's already OK, some systems remove
4510 * permission or ACL stuff */
4511 if (mch_stat((char *)wfname, &st) < 0
4512 || st.st_uid != st_old.st_uid
4513 || st.st_gid != st_old.st_gid)
4514 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004515 ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004516 if (perm >= 0) /* set permission again, may have changed */
4517 (void)mch_setperm(wfname, perm);
4518 }
4519# endif
4520 buf_setino(buf);
4521 }
Bram Moolenaarf1726cc2009-05-13 18:48:16 +00004522 else if (!buf->b_dev_valid)
Bram Moolenaar8fa04452005-12-23 22:13:51 +00004523 /* Set the inode when creating a new file. */
4524 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004525#endif
4526
Bram Moolenaar071d4272004-06-13 20:20:40 +00004527 if (close(fd) != 0)
4528 {
4529 errmsg = (char_u *)_("E512: Close failed");
4530 end = 0;
4531 }
4532
4533#ifdef UNIX
4534 if (made_writable)
4535 perm &= ~0200; /* reset 'w' bit for security reasons */
4536#endif
4537 if (perm >= 0) /* set perm. of new file same as old file */
4538 (void)mch_setperm(wfname, perm);
4539#ifdef RISCOS
4540 if (!append && !filtering)
4541 /* Set the filetype after writing the file. */
4542 mch_set_filetype(wfname, buf->b_p_oft);
4543#endif
4544#ifdef HAVE_ACL
4545 /* Probably need to set the ACL before changing the user (can't set the
4546 * ACL on a file the user doesn't own). */
4547 if (!backup_copy)
4548 mch_set_acl(wfname, acl);
4549#endif
4550
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551
4552#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4553 if (wfname != fname)
4554 {
4555 /*
4556 * The file was written to a temp file, now it needs to be converted
4557 * with 'charconvert' to (overwrite) the output file.
4558 */
4559 if (end != 0)
4560 {
4561 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4562 wfname, fname) == FAIL)
4563 {
4564 write_info.bw_conv_error = TRUE;
4565 end = 0;
4566 }
4567 }
4568 mch_remove(wfname);
4569 vim_free(wfname);
4570 }
4571#endif
4572
4573 if (end == 0)
4574 {
4575 if (errmsg == NULL)
4576 {
4577#ifdef FEAT_MBYTE
4578 if (write_info.bw_conv_error)
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004579 {
4580 if (write_info.bw_conv_error_lnum == 0)
4581 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
4582 else
4583 {
4584 errmsg_allocated = TRUE;
4585 errmsg = alloc(300);
4586 vim_snprintf((char *)errmsg, 300, _("E513: write error, conversion failed in line %ld (make 'fenc' empty to override)"),
4587 (long)write_info.bw_conv_error_lnum);
4588 }
4589 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004590 else
4591#endif
4592 if (got_int)
4593 errmsg = (char_u *)_(e_interr);
4594 else
4595 errmsg = (char_u *)_("E514: write error (file system full?)");
4596 }
4597
4598 /*
4599 * If we have a backup file, try to put it in place of the new file,
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004600 * because the new file is probably corrupt. This avoids losing the
Bram Moolenaar071d4272004-06-13 20:20:40 +00004601 * original file when trying to make a backup when writing the file a
4602 * second time.
4603 * When "backup_copy" is set we need to copy the backup over the new
4604 * file. Otherwise rename the backup file.
4605 * If this is OK, don't give the extra warning message.
4606 */
4607 if (backup != NULL)
4608 {
4609 if (backup_copy)
4610 {
4611 /* This may take a while, if we were interrupted let the user
4612 * know we got the message. */
4613 if (got_int)
4614 {
4615 MSG(_(e_interr));
4616 out_flush();
4617 }
4618 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4619 {
4620 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004621 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4622 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004623 {
4624 /* copy the file. */
4625 write_info.bw_buf = smallbuf;
4626#ifdef HAS_BW_FLAGS
4627 write_info.bw_flags = FIO_NOCONVERT;
4628#endif
4629 while ((write_info.bw_len = vim_read(fd, smallbuf,
4630 SMBUFSIZE)) > 0)
4631 if (buf_write_bytes(&write_info) == FAIL)
4632 break;
4633
4634 if (close(write_info.bw_fd) >= 0
4635 && write_info.bw_len == 0)
4636 end = 1; /* success */
4637 }
4638 close(fd); /* ignore errors for closing read file */
4639 }
4640 }
4641 else
4642 {
4643 if (vim_rename(backup, fname) == 0)
4644 end = 1;
4645 }
4646 }
4647 goto fail;
4648 }
4649
4650 lnum -= start; /* compute number of written lines */
4651 --no_wait_return; /* may wait for return now */
4652
4653#if !(defined(UNIX) || defined(VMS))
4654 fname = sfname; /* use shortname now, for the messages */
4655#endif
4656 if (!filtering)
4657 {
4658 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4659 c = FALSE;
4660#ifdef FEAT_MBYTE
4661 if (write_info.bw_conv_error)
4662 {
4663 STRCAT(IObuff, _(" CONVERSION ERROR"));
4664 c = TRUE;
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004665 if (write_info.bw_conv_error_lnum != 0)
4666 {
Bram Moolenaarc0662022009-09-11 13:04:24 +00004667 size_t l = STRLEN(IObuff);
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004668 vim_snprintf((char *)IObuff + l, IOSIZE - l, _(" in line %ld;"),
4669 (long)write_info.bw_conv_error_lnum);
4670 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004671 }
4672 else if (notconverted)
4673 {
4674 STRCAT(IObuff, _("[NOT converted]"));
4675 c = TRUE;
4676 }
4677 else if (converted)
4678 {
4679 STRCAT(IObuff, _("[converted]"));
4680 c = TRUE;
4681 }
4682#endif
4683 if (device)
4684 {
4685 STRCAT(IObuff, _("[Device]"));
4686 c = TRUE;
4687 }
4688 else if (newfile)
4689 {
4690 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4691 c = TRUE;
4692 }
4693 if (no_eol)
4694 {
4695 msg_add_eol();
4696 c = TRUE;
4697 }
4698 /* may add [unix/dos/mac] */
4699 if (msg_add_fileformat(fileformat))
4700 c = TRUE;
4701#ifdef FEAT_CRYPT
4702 if (wb_flags & FIO_ENCRYPTED)
4703 {
4704 STRCAT(IObuff, _("[crypted]"));
4705 c = TRUE;
4706 }
4707#endif
4708 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4709 if (!shortmess(SHM_WRITE))
4710 {
4711 if (append)
4712 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4713 else
4714 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4715 }
4716
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00004717 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004718 }
4719
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004720 /* When written everything correctly: reset 'modified'. Unless not
4721 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00004722 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00004723#ifdef FEAT_MBYTE
4724 && !write_info.bw_conv_error
4725#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004726 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4727 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004728 {
4729 unchanged(buf, TRUE);
4730 u_unchanged(buf);
4731 }
4732
4733 /*
4734 * If written to the current file, update the timestamp of the swap file
4735 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4736 */
4737 if (overwriting)
4738 {
4739 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00004740 if (append)
4741 buf->b_flags &= ~BF_NEW;
4742 else
4743 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004744 }
4745
4746 /*
4747 * If we kept a backup until now, and we are in patch mode, then we make
4748 * the backup file our 'original' file.
4749 */
4750 if (*p_pm && dobackup)
4751 {
4752 char *org = (char *)buf_modname(
4753#ifdef SHORT_FNAME
4754 TRUE,
4755#else
4756 (buf->b_p_sn || buf->b_shortname),
4757#endif
4758 fname, p_pm, FALSE);
4759
4760 if (backup != NULL)
4761 {
4762 struct stat st;
4763
4764 /*
4765 * If the original file does not exist yet
4766 * the current backup file becomes the original file
4767 */
4768 if (org == NULL)
4769 EMSG(_("E205: Patchmode: can't save original file"));
4770 else if (mch_stat(org, &st) < 0)
4771 {
4772 vim_rename(backup, (char_u *)org);
4773 vim_free(backup); /* don't delete the file */
4774 backup = NULL;
4775#ifdef UNIX
4776 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4777#endif
4778 }
4779 }
4780 /*
4781 * If there is no backup file, remember that a (new) file was
4782 * created.
4783 */
4784 else
4785 {
4786 int empty_fd;
4787
4788 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00004789 || (empty_fd = mch_open(org,
4790 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004791 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 EMSG(_("E206: patchmode: can't touch empty original file"));
4793 else
4794 close(empty_fd);
4795 }
4796 if (org != NULL)
4797 {
4798 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4799 vim_free(org);
4800 }
4801 }
4802
4803 /*
4804 * Remove the backup unless 'backup' option is set
4805 */
4806 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4807 EMSG(_("E207: Can't delete backup file"));
4808
4809#ifdef FEAT_SUN_WORKSHOP
4810 if (usingSunWorkShop)
4811 workshop_file_saved((char *) ffname);
4812#endif
4813
4814 goto nofail;
4815
4816 /*
4817 * Finish up. We get here either after failure or success.
4818 */
4819fail:
4820 --no_wait_return; /* may wait for return now */
4821nofail:
4822
4823 /* Done saving, we accept changed buffer warnings again */
4824 buf->b_saving = FALSE;
4825
4826 vim_free(backup);
4827 if (buffer != smallbuf)
4828 vim_free(buffer);
4829#ifdef FEAT_MBYTE
4830 vim_free(fenc_tofree);
4831 vim_free(write_info.bw_conv_buf);
4832# ifdef USE_ICONV
4833 if (write_info.bw_iconv_fd != (iconv_t)-1)
4834 {
4835 iconv_close(write_info.bw_iconv_fd);
4836 write_info.bw_iconv_fd = (iconv_t)-1;
4837 }
4838# endif
4839#endif
4840#ifdef HAVE_ACL
4841 mch_free_acl(acl);
4842#endif
4843
4844 if (errmsg != NULL)
4845 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004846 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004847
4848 attr = hl_attr(HLF_E); /* set highlight for error messages */
4849 msg_add_fname(buf,
4850#ifndef UNIX
4851 sfname
4852#else
4853 fname
4854#endif
4855 ); /* put file name in IObuff with quotes */
4856 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4857 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4858 /* If the error message has the form "is ...", put the error number in
4859 * front of the file name. */
4860 if (errnum != NULL)
4861 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00004862 STRMOVE(IObuff + numlen, IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004863 mch_memmove(IObuff, errnum, (size_t)numlen);
4864 }
4865 STRCAT(IObuff, errmsg);
4866 emsg(IObuff);
Bram Moolenaar32b485f2009-07-29 16:06:27 +00004867 if (errmsg_allocated)
4868 vim_free(errmsg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004869
4870 retval = FAIL;
4871 if (end == 0)
4872 {
4873 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4874 attr | MSG_HIST);
4875 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4876 attr | MSG_HIST);
4877
4878 /* Update the timestamp to avoid an "overwrite changed file"
4879 * prompt when writing again. */
4880 if (mch_stat((char *)fname, &st_old) >= 0)
4881 {
4882 buf_store_time(buf, &st_old, fname);
4883 buf->b_mtime_read = buf->b_mtime;
4884 }
4885 }
4886 }
4887 msg_scroll = msg_save;
4888
4889#ifdef FEAT_AUTOCMD
4890#ifdef FEAT_EVAL
4891 if (!should_abort(retval))
4892#else
4893 if (!got_int)
4894#endif
4895 {
4896 aco_save_T aco;
4897
4898 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4899
4900 /*
4901 * Apply POST autocommands.
4902 * Careful: The autocommands may call buf_write() recursively!
4903 */
4904 aucmd_prepbuf(&aco, buf);
4905
4906 if (append)
4907 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4908 FALSE, curbuf, eap);
4909 else if (filtering)
4910 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4911 FALSE, curbuf, eap);
4912 else if (reset_changed && whole)
4913 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4914 FALSE, curbuf, eap);
4915 else
4916 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4917 FALSE, curbuf, eap);
4918
4919 /* restore curwin/curbuf and a few other things */
4920 aucmd_restbuf(&aco);
4921
4922#ifdef FEAT_EVAL
4923 if (aborting()) /* autocmds may abort script processing */
4924 retval = FALSE;
4925#endif
4926 }
4927#endif
4928
4929 got_int |= prev_got_int;
4930
4931#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4932 /* Update machine specific information. */
4933 mch_post_buffer_write(buf);
4934#endif
4935 return retval;
4936}
4937
4938/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004939 * Set the name of the current buffer. Use when the buffer doesn't have a
4940 * name and a ":r" or ":w" command with a file name is used.
4941 */
4942 static int
4943set_rw_fname(fname, sfname)
4944 char_u *fname;
4945 char_u *sfname;
4946{
4947#ifdef FEAT_AUTOCMD
Bram Moolenaar8b38e242009-06-16 13:35:20 +00004948 buf_T *buf = curbuf;
4949
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004950 /* It's like the unnamed buffer is deleted.... */
4951 if (curbuf->b_p_bl)
4952 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
4953 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
4954# ifdef FEAT_EVAL
4955 if (aborting()) /* autocmds may abort script processing */
4956 return FAIL;
4957# endif
Bram Moolenaar8b38e242009-06-16 13:35:20 +00004958 if (curbuf != buf)
4959 {
4960 /* We are in another buffer now, don't do the renaming. */
4961 EMSG(_(e_auchangedbuf));
4962 return FAIL;
4963 }
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004964#endif
4965
4966 if (setfname(curbuf, fname, sfname, FALSE) == OK)
4967 curbuf->b_flags |= BF_NOTEDITED;
4968
4969#ifdef FEAT_AUTOCMD
4970 /* ....and a new named one is created */
4971 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
4972 if (curbuf->b_p_bl)
4973 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
4974# ifdef FEAT_EVAL
4975 if (aborting()) /* autocmds may abort script processing */
4976 return FAIL;
4977# endif
4978
4979 /* Do filetype detection now if 'filetype' is empty. */
4980 if (*curbuf->b_p_ft == NUL)
4981 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004982 if (au_has_group((char_u *)"filetypedetect"))
Bram Moolenaar70836c82006-02-20 21:28:49 +00004983 (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE);
Bram Moolenaara3227e22006-03-08 21:32:40 +00004984 do_modelines(0);
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004985 }
4986#endif
4987
4988 return OK;
4989}
4990
4991/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004992 * Put file name into IObuff with quotes.
4993 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004994 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004995msg_add_fname(buf, fname)
4996 buf_T *buf;
4997 char_u *fname;
4998{
4999 if (fname == NULL)
5000 fname = (char_u *)"-stdin-";
5001 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
5002 IObuff[0] = '"';
5003 STRCAT(IObuff, "\" ");
5004}
5005
5006/*
5007 * Append message for text mode to IObuff.
5008 * Return TRUE if something appended.
5009 */
5010 static int
5011msg_add_fileformat(eol_type)
5012 int eol_type;
5013{
5014#ifndef USE_CRNL
5015 if (eol_type == EOL_DOS)
5016 {
5017 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
5018 return TRUE;
5019 }
5020#endif
5021#ifndef USE_CR
5022 if (eol_type == EOL_MAC)
5023 {
5024 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
5025 return TRUE;
5026 }
5027#endif
5028#if defined(USE_CRNL) || defined(USE_CR)
5029 if (eol_type == EOL_UNIX)
5030 {
5031 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
5032 return TRUE;
5033 }
5034#endif
5035 return FALSE;
5036}
5037
5038/*
5039 * Append line and character count to IObuff.
5040 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00005041 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00005042msg_add_lines(insert_space, lnum, nchars)
5043 int insert_space;
5044 long lnum;
5045 long nchars;
5046{
5047 char_u *p;
5048
5049 p = IObuff + STRLEN(IObuff);
5050
5051 if (insert_space)
5052 *p++ = ' ';
5053 if (shortmess(SHM_LINES))
5054 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
5055 else
5056 {
5057 if (lnum == 1)
5058 STRCPY(p, _("1 line, "));
5059 else
5060 sprintf((char *)p, _("%ld lines, "), lnum);
5061 p += STRLEN(p);
5062 if (nchars == 1)
5063 STRCPY(p, _("1 character"));
5064 else
5065 sprintf((char *)p, _("%ld characters"), nchars);
5066 }
5067}
5068
5069/*
5070 * Append message for missing line separator to IObuff.
5071 */
5072 static void
5073msg_add_eol()
5074{
5075 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
5076}
5077
5078/*
5079 * Check modification time of file, before writing to it.
5080 * The size isn't checked, because using a tool like "gzip" takes care of
5081 * using the same timestamp but can't set the size.
5082 */
5083 static int
5084check_mtime(buf, st)
5085 buf_T *buf;
5086 struct stat *st;
5087{
5088 if (buf->b_mtime_read != 0
5089 && time_differs((long)st->st_mtime, buf->b_mtime_read))
5090 {
5091 msg_scroll = TRUE; /* don't overwrite messages here */
5092 msg_silent = 0; /* must give this prompt */
5093 /* don't use emsg() here, don't want to flush the buffers */
5094 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
5095 hl_attr(HLF_E));
5096 if (ask_yesno((char_u *)_("Do you really want to write to it"),
5097 TRUE) == 'n')
5098 return FAIL;
5099 msg_scroll = FALSE; /* always overwrite the file message now */
5100 }
5101 return OK;
5102}
5103
5104 static int
5105time_differs(t1, t2)
5106 long t1, t2;
5107{
5108#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
5109 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
5110 * the seconds. Since the roundoff is done when flushing the inode, the
5111 * time may change unexpectedly by one second!!! */
5112 return (t1 - t2 > 1 || t2 - t1 > 1);
5113#else
5114 return (t1 != t2);
5115#endif
5116}
5117
5118/*
5119 * Call write() to write a number of bytes to the file.
5120 * Also handles encryption and 'encoding' conversion.
5121 *
5122 * Return FAIL for failure, OK otherwise.
5123 */
5124 static int
5125buf_write_bytes(ip)
5126 struct bw_info *ip;
5127{
5128 int wlen;
5129 char_u *buf = ip->bw_buf; /* data to write */
5130 int len = ip->bw_len; /* length of data */
5131#ifdef HAS_BW_FLAGS
5132 int flags = ip->bw_flags; /* extra flags */
5133#endif
5134
5135#ifdef FEAT_MBYTE
5136 /*
5137 * Skip conversion when writing the crypt magic number or the BOM.
5138 */
5139 if (!(flags & FIO_NOCONVERT))
5140 {
5141 char_u *p;
5142 unsigned c;
5143 int n;
5144
5145 if (flags & FIO_UTF8)
5146 {
5147 /*
5148 * Convert latin1 in the buffer to UTF-8 in the file.
5149 */
5150 p = ip->bw_conv_buf; /* translate to buffer */
5151 for (wlen = 0; wlen < len; ++wlen)
5152 p += utf_char2bytes(buf[wlen], p);
5153 buf = ip->bw_conv_buf;
5154 len = (int)(p - ip->bw_conv_buf);
5155 }
5156 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
5157 {
5158 /*
5159 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
5160 * Latin1 chars in the file.
5161 */
5162 if (flags & FIO_LATIN1)
5163 p = buf; /* translate in-place (can only get shorter) */
5164 else
5165 p = ip->bw_conv_buf; /* translate to buffer */
5166 for (wlen = 0; wlen < len; wlen += n)
5167 {
5168 if (wlen == 0 && ip->bw_restlen != 0)
5169 {
5170 int l;
5171
5172 /* Use remainder of previous call. Append the start of
5173 * buf[] to get a full sequence. Might still be too
5174 * short! */
5175 l = CONV_RESTLEN - ip->bw_restlen;
5176 if (l > len)
5177 l = len;
5178 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005179 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005180 if (n > ip->bw_restlen + len)
5181 {
5182 /* We have an incomplete byte sequence at the end to
5183 * be written. We can't convert it without the
5184 * remaining bytes. Keep them for the next call. */
5185 if (ip->bw_restlen + len > CONV_RESTLEN)
5186 return FAIL;
5187 ip->bw_restlen += len;
5188 break;
5189 }
5190 if (n > 1)
5191 c = utf_ptr2char(ip->bw_rest);
5192 else
5193 c = ip->bw_rest[0];
5194 if (n >= ip->bw_restlen)
5195 {
5196 n -= ip->bw_restlen;
5197 ip->bw_restlen = 0;
5198 }
5199 else
5200 {
5201 ip->bw_restlen -= n;
5202 mch_memmove(ip->bw_rest, ip->bw_rest + n,
5203 (size_t)ip->bw_restlen);
5204 n = 0;
5205 }
5206 }
5207 else
5208 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00005209 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210 if (n > len - wlen)
5211 {
5212 /* We have an incomplete byte sequence at the end to
5213 * be written. We can't convert it without the
5214 * remaining bytes. Keep them for the next call. */
5215 if (len - wlen > CONV_RESTLEN)
5216 return FAIL;
5217 ip->bw_restlen = len - wlen;
5218 mch_memmove(ip->bw_rest, buf + wlen,
5219 (size_t)ip->bw_restlen);
5220 break;
5221 }
5222 if (n > 1)
5223 c = utf_ptr2char(buf + wlen);
5224 else
5225 c = buf[wlen];
5226 }
5227
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005228 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error)
5229 {
5230 ip->bw_conv_error = TRUE;
5231 ip->bw_conv_error_lnum = ip->bw_start_lnum;
5232 }
5233 if (c == NL)
5234 ++ip->bw_start_lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005235 }
5236 if (flags & FIO_LATIN1)
5237 len = (int)(p - buf);
5238 else
5239 {
5240 buf = ip->bw_conv_buf;
5241 len = (int)(p - ip->bw_conv_buf);
5242 }
5243 }
5244
5245# ifdef WIN3264
5246 else if (flags & FIO_CODEPAGE)
5247 {
5248 /*
5249 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
5250 * codepage.
5251 */
5252 char_u *from;
5253 size_t fromlen;
5254 char_u *to;
5255 int u8c;
5256 BOOL bad = FALSE;
5257 int needed;
5258
5259 if (ip->bw_restlen > 0)
5260 {
5261 /* Need to concatenate the remainder of the previous call and
5262 * the bytes of the current call. Use the end of the
5263 * conversion buffer for this. */
5264 fromlen = len + ip->bw_restlen;
5265 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5266 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5267 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5268 }
5269 else
5270 {
5271 from = buf;
5272 fromlen = len;
5273 }
5274
5275 to = ip->bw_conv_buf;
5276 if (enc_utf8)
5277 {
5278 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
5279 * The buffer has been allocated to be big enough. */
5280 while (fromlen > 0)
5281 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005282 n = (int)utf_ptr2len_len(from, (int)fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005283 if (n > (int)fromlen) /* incomplete byte sequence */
5284 break;
5285 u8c = utf_ptr2char(from);
5286 *to++ = (u8c & 0xff);
5287 *to++ = (u8c >> 8);
5288 fromlen -= n;
5289 from += n;
5290 }
5291
5292 /* Copy remainder to ip->bw_rest[] to be used for the next
5293 * call. */
5294 if (fromlen > CONV_RESTLEN)
5295 {
5296 /* weird overlong sequence */
5297 ip->bw_conv_error = TRUE;
5298 return FAIL;
5299 }
5300 mch_memmove(ip->bw_rest, from, fromlen);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005301 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005302 }
5303 else
5304 {
5305 /* Convert from enc_codepage to UCS-2, to the start of the
5306 * buffer. The buffer has been allocated to be big enough. */
5307 ip->bw_restlen = 0;
5308 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005309 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005310 NULL, 0);
5311 if (needed == 0)
5312 {
5313 /* When conversion fails there may be a trailing byte. */
5314 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005315 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005316 NULL, 0);
5317 if (needed == 0)
5318 {
5319 /* Conversion doesn't work. */
5320 ip->bw_conv_error = TRUE;
5321 return FAIL;
5322 }
5323 /* Save the trailing byte for the next call. */
5324 ip->bw_rest[0] = from[fromlen - 1];
5325 ip->bw_restlen = 1;
5326 }
5327 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005328 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005329 (LPWSTR)to, needed);
5330 if (needed == 0)
5331 {
5332 /* Safety check: Conversion doesn't work. */
5333 ip->bw_conv_error = TRUE;
5334 return FAIL;
5335 }
5336 to += needed * 2;
5337 }
5338
5339 fromlen = to - ip->bw_conv_buf;
5340 buf = to;
5341# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5342 if (FIO_GET_CP(flags) == CP_UTF8)
5343 {
5344 /* Convert from UCS-2 to UTF-8, using the remainder of the
5345 * conversion buffer. Fails when out of space. */
5346 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
5347 {
5348 u8c = *from++;
5349 u8c += (*from++ << 8);
5350 to += utf_char2bytes(u8c, to);
5351 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
5352 {
5353 ip->bw_conv_error = TRUE;
5354 return FAIL;
5355 }
5356 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005357 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005358 }
5359 else
5360#endif
5361 {
5362 /* Convert from UCS-2 to the codepage, using the remainder of
5363 * the conversion buffer. If the conversion uses the default
5364 * character "0", the data doesn't fit in this encoding, so
5365 * fail. */
5366 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5367 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005368 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0,
5369 &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005370 if (bad)
5371 {
5372 ip->bw_conv_error = TRUE;
5373 return FAIL;
5374 }
5375 }
5376 }
5377# endif
5378
Bram Moolenaar56718732006-03-15 22:53:57 +00005379# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005380 else if (flags & FIO_MACROMAN)
5381 {
5382 /*
5383 * Convert UTF-8 or latin1 to Apple MacRoman.
5384 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005385 char_u *from;
5386 size_t fromlen;
5387
5388 if (ip->bw_restlen > 0)
5389 {
5390 /* Need to concatenate the remainder of the previous call and
5391 * the bytes of the current call. Use the end of the
5392 * conversion buffer for this. */
5393 fromlen = len + ip->bw_restlen;
5394 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5395 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5396 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5397 }
5398 else
5399 {
5400 from = buf;
5401 fromlen = len;
5402 }
5403
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005404 if (enc2macroman(from, fromlen,
5405 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5406 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 {
5408 ip->bw_conv_error = TRUE;
5409 return FAIL;
5410 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005411 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412 }
5413# endif
5414
5415# ifdef USE_ICONV
5416 if (ip->bw_iconv_fd != (iconv_t)-1)
5417 {
5418 const char *from;
5419 size_t fromlen;
5420 char *to;
5421 size_t tolen;
5422
5423 /* Convert with iconv(). */
5424 if (ip->bw_restlen > 0)
5425 {
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005426 char *fp;
5427
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 /* Need to concatenate the remainder of the previous call and
5429 * the bytes of the current call. Use the end of the
5430 * conversion buffer for this. */
5431 fromlen = len + ip->bw_restlen;
Bram Moolenaar5d294d12009-03-11 12:11:02 +00005432 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5433 mch_memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
5434 mch_memmove(fp + ip->bw_restlen, buf, (size_t)len);
5435 from = fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005436 tolen = ip->bw_conv_buflen - fromlen;
5437 }
5438 else
5439 {
5440 from = (const char *)buf;
5441 fromlen = len;
5442 tolen = ip->bw_conv_buflen;
5443 }
5444 to = (char *)ip->bw_conv_buf;
5445
5446 if (ip->bw_first)
5447 {
5448 size_t save_len = tolen;
5449
5450 /* output the initial shift state sequence */
5451 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5452
5453 /* There is a bug in iconv() on Linux (which appears to be
5454 * wide-spread) which sets "to" to NULL and messes up "tolen".
5455 */
5456 if (to == NULL)
5457 {
5458 to = (char *)ip->bw_conv_buf;
5459 tolen = save_len;
5460 }
5461 ip->bw_first = FALSE;
5462 }
5463
5464 /*
5465 * If iconv() has an error or there is not enough room, fail.
5466 */
5467 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5468 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5469 || fromlen > CONV_RESTLEN)
5470 {
5471 ip->bw_conv_error = TRUE;
5472 return FAIL;
5473 }
5474
5475 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5476 if (fromlen > 0)
5477 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5478 ip->bw_restlen = (int)fromlen;
5479
5480 buf = ip->bw_conv_buf;
5481 len = (int)((char_u *)to - ip->bw_conv_buf);
5482 }
5483# endif
5484 }
5485#endif /* FEAT_MBYTE */
5486
5487#ifdef FEAT_CRYPT
5488 if (flags & FIO_ENCRYPTED) /* encrypt the data */
5489 {
5490 int ztemp, t, i;
5491
5492 for (i = 0; i < len; i++)
5493 {
5494 ztemp = buf[i];
5495 buf[i] = ZENCODE(ztemp, t);
5496 }
5497 }
5498#endif
5499
5500 /* Repeat the write(), it may be interrupted by a signal. */
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005501 while (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005502 {
5503 wlen = vim_write(ip->bw_fd, buf, len);
5504 if (wlen <= 0) /* error! */
5505 return FAIL;
5506 len -= wlen;
5507 buf += wlen;
5508 }
5509 return OK;
5510}
5511
5512#ifdef FEAT_MBYTE
5513/*
5514 * Convert a Unicode character to bytes.
Bram Moolenaar32b485f2009-07-29 16:06:27 +00005515 * Return TRUE for an error, FALSE when it's OK.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005516 */
5517 static int
5518ucs2bytes(c, pp, flags)
5519 unsigned c; /* in: character */
5520 char_u **pp; /* in/out: pointer to result */
5521 int flags; /* FIO_ flags */
5522{
5523 char_u *p = *pp;
5524 int error = FALSE;
5525 int cc;
5526
5527
5528 if (flags & FIO_UCS4)
5529 {
5530 if (flags & FIO_ENDIAN_L)
5531 {
5532 *p++ = c;
5533 *p++ = (c >> 8);
5534 *p++ = (c >> 16);
5535 *p++ = (c >> 24);
5536 }
5537 else
5538 {
5539 *p++ = (c >> 24);
5540 *p++ = (c >> 16);
5541 *p++ = (c >> 8);
5542 *p++ = c;
5543 }
5544 }
5545 else if (flags & (FIO_UCS2 | FIO_UTF16))
5546 {
5547 if (c >= 0x10000)
5548 {
5549 if (flags & FIO_UTF16)
5550 {
5551 /* Make two words, ten bits of the character in each. First
5552 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5553 c -= 0x10000;
5554 if (c >= 0x100000)
5555 error = TRUE;
5556 cc = ((c >> 10) & 0x3ff) + 0xd800;
5557 if (flags & FIO_ENDIAN_L)
5558 {
5559 *p++ = cc;
5560 *p++ = ((unsigned)cc >> 8);
5561 }
5562 else
5563 {
5564 *p++ = ((unsigned)cc >> 8);
5565 *p++ = cc;
5566 }
5567 c = (c & 0x3ff) + 0xdc00;
5568 }
5569 else
5570 error = TRUE;
5571 }
5572 if (flags & FIO_ENDIAN_L)
5573 {
5574 *p++ = c;
5575 *p++ = (c >> 8);
5576 }
5577 else
5578 {
5579 *p++ = (c >> 8);
5580 *p++ = c;
5581 }
5582 }
5583 else /* Latin1 */
5584 {
5585 if (c >= 0x100)
5586 {
5587 error = TRUE;
5588 *p++ = 0xBF;
5589 }
5590 else
5591 *p++ = c;
5592 }
5593
5594 *pp = p;
5595 return error;
5596}
5597
5598/*
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005599 * Return TRUE if file encoding "fenc" requires conversion from or to
5600 * 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005601 */
5602 static int
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005603need_conversion(fenc)
5604 char_u *fenc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005605{
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005606 int same_encoding;
5607 int enc_flags;
5608 int fenc_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005609
Bram Moolenaarb5cdf2e2009-07-29 16:25:31 +00005610 if (*fenc == NUL || STRCMP(p_enc, fenc) == 0)
5611 same_encoding = TRUE;
5612 else
5613 {
5614 /* Ignore difference between "ansi" and "latin1", "ucs-4" and
5615 * "ucs-4be", etc. */
5616 enc_flags = get_fio_flags(p_enc);
5617 fenc_flags = get_fio_flags(fenc);
5618 same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
5619 }
5620 if (same_encoding)
5621 {
5622 /* Specified encoding matches with 'encoding'. This requires
5623 * conversion when 'encoding' is Unicode but not UTF-8. */
5624 return enc_unicode != 0;
5625 }
5626
5627 /* Encodings differ. However, conversion is not needed when 'enc' is any
5628 * Unicode encoding and the file is UTF-8. */
5629 return !(enc_utf8 && fenc_flags == FIO_UTF8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005630}
5631
5632/*
5633 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5634 * internal conversion.
5635 * if "ptr" is an empty string, use 'encoding'.
5636 */
5637 static int
5638get_fio_flags(ptr)
5639 char_u *ptr;
5640{
5641 int prop;
5642
5643 if (*ptr == NUL)
5644 ptr = p_enc;
5645
5646 prop = enc_canon_props(ptr);
5647 if (prop & ENC_UNICODE)
5648 {
5649 if (prop & ENC_2BYTE)
5650 {
5651 if (prop & ENC_ENDIAN_L)
5652 return FIO_UCS2 | FIO_ENDIAN_L;
5653 return FIO_UCS2;
5654 }
5655 if (prop & ENC_4BYTE)
5656 {
5657 if (prop & ENC_ENDIAN_L)
5658 return FIO_UCS4 | FIO_ENDIAN_L;
5659 return FIO_UCS4;
5660 }
5661 if (prop & ENC_2WORD)
5662 {
5663 if (prop & ENC_ENDIAN_L)
5664 return FIO_UTF16 | FIO_ENDIAN_L;
5665 return FIO_UTF16;
5666 }
5667 return FIO_UTF8;
5668 }
5669 if (prop & ENC_LATIN1)
5670 return FIO_LATIN1;
5671 /* must be ENC_DBCS, requires iconv() */
5672 return 0;
5673}
5674
5675#ifdef WIN3264
5676/*
5677 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5678 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5679 * Used for conversion between 'encoding' and 'fileencoding'.
5680 */
5681 static int
5682get_win_fio_flags(ptr)
5683 char_u *ptr;
5684{
5685 int cp;
5686
5687 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5688 if (!enc_utf8 && enc_codepage <= 0)
5689 return 0;
5690
5691 cp = encname2codepage(ptr);
5692 if (cp == 0)
5693 {
5694# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5695 if (STRCMP(ptr, "utf-8") == 0)
5696 cp = CP_UTF8;
5697 else
5698# endif
5699 return 0;
5700 }
5701 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5702}
5703#endif
5704
5705#ifdef MACOS_X
5706/*
5707 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5708 * needed for the internal conversion to/from utf-8 or latin1.
5709 */
5710 static int
5711get_mac_fio_flags(ptr)
5712 char_u *ptr;
5713{
5714 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5715 && (enc_canon_props(ptr) & ENC_MACROMAN))
5716 return FIO_MACROMAN;
5717 return 0;
5718}
5719#endif
5720
5721/*
5722 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5723 * "size" must be at least 2.
5724 * Return the name of the encoding and set "*lenp" to the length.
5725 * Returns NULL when no BOM found.
5726 */
5727 static char_u *
5728check_for_bom(p, size, lenp, flags)
5729 char_u *p;
5730 long size;
5731 int *lenp;
5732 int flags;
5733{
5734 char *name = NULL;
5735 int len = 2;
5736
5737 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
Bram Moolenaaree0f5a62008-07-24 20:09:16 +00005738 && (flags == FIO_ALL || flags == FIO_UTF8 || flags == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005739 {
5740 name = "utf-8"; /* EF BB BF */
5741 len = 3;
5742 }
5743 else if (p[0] == 0xff && p[1] == 0xfe)
5744 {
5745 if (size >= 4 && p[2] == 0 && p[3] == 0
5746 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5747 {
5748 name = "ucs-4le"; /* FF FE 00 00 */
5749 len = 4;
5750 }
Bram Moolenaar223a1892008-11-11 20:57:11 +00005751 else if (flags == (FIO_UCS2 | FIO_ENDIAN_L))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005752 name = "ucs-2le"; /* FF FE */
Bram Moolenaar223a1892008-11-11 20:57:11 +00005753 else if (flags == FIO_ALL || flags == (FIO_UTF16 | FIO_ENDIAN_L))
5754 /* utf-16le is preferred, it also works for ucs-2le text */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005755 name = "utf-16le"; /* FF FE */
5756 }
5757 else if (p[0] == 0xfe && p[1] == 0xff
5758 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5759 {
Bram Moolenaarffd82c52008-02-20 17:15:26 +00005760 /* Default to utf-16, it works also for ucs-2 text. */
5761 if (flags == FIO_UCS2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005762 name = "ucs-2"; /* FE FF */
Bram Moolenaarffd82c52008-02-20 17:15:26 +00005763 else
5764 name = "utf-16"; /* FE FF */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005765 }
5766 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5767 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5768 {
5769 name = "ucs-4"; /* 00 00 FE FF */
5770 len = 4;
5771 }
5772
5773 *lenp = len;
5774 return (char_u *)name;
5775}
5776
5777/*
5778 * Generate a BOM in "buf[4]" for encoding "name".
5779 * Return the length of the BOM (zero when no BOM).
5780 */
5781 static int
5782make_bom(buf, name)
5783 char_u *buf;
5784 char_u *name;
5785{
5786 int flags;
5787 char_u *p;
5788
5789 flags = get_fio_flags(name);
5790
5791 /* Can't put a BOM in a non-Unicode file. */
5792 if (flags == FIO_LATIN1 || flags == 0)
5793 return 0;
5794
5795 if (flags == FIO_UTF8) /* UTF-8 */
5796 {
5797 buf[0] = 0xef;
5798 buf[1] = 0xbb;
5799 buf[2] = 0xbf;
5800 return 3;
5801 }
5802 p = buf;
5803 (void)ucs2bytes(0xfeff, &p, flags);
5804 return (int)(p - buf);
5805}
5806#endif
5807
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00005808#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \
Bram Moolenaara0174af2008-01-02 20:08:25 +00005809 defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005810/*
5811 * Try to find a shortname by comparing the fullname with the current
5812 * directory.
Bram Moolenaard089d9b2007-09-30 12:02:55 +00005813 * Returns "full_path" or pointer into "full_path" if shortened.
5814 */
5815 char_u *
5816shorten_fname1(full_path)
5817 char_u *full_path;
5818{
5819 char_u dirname[MAXPATHL];
5820 char_u *p = full_path;
5821
5822 if (mch_dirname(dirname, MAXPATHL) == OK)
5823 {
5824 p = shorten_fname(full_path, dirname);
5825 if (p == NULL || *p == NUL)
5826 p = full_path;
5827 }
5828 return p;
5829}
Bram Moolenaard4cacdf2007-10-03 10:50:10 +00005830#endif
Bram Moolenaard089d9b2007-09-30 12:02:55 +00005831
5832/*
5833 * Try to find a shortname by comparing the fullname with the current
5834 * directory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005835 * Returns NULL if not shorter name possible, pointer into "full_path"
5836 * otherwise.
5837 */
5838 char_u *
5839shorten_fname(full_path, dir_name)
5840 char_u *full_path;
5841 char_u *dir_name;
5842{
5843 int len;
5844 char_u *p;
5845
5846 if (full_path == NULL)
5847 return NULL;
5848 len = (int)STRLEN(dir_name);
5849 if (fnamencmp(dir_name, full_path, len) == 0)
5850 {
5851 p = full_path + len;
5852#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5853 /*
5854 * MSDOS: when a file is in the root directory, dir_name will end in a
5855 * slash, since C: by itself does not define a specific dir. In this
5856 * case p may already be correct. <negri>
5857 */
5858 if (!((len > 2) && (*(p - 2) == ':')))
5859#endif
5860 {
5861 if (vim_ispathsep(*p))
5862 ++p;
5863#ifndef VMS /* the path separator is always part of the path */
5864 else
5865 p = NULL;
5866#endif
5867 }
5868 }
5869#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5870 /*
5871 * When using a file in the current drive, remove the drive name:
5872 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5873 * a floppy from "A:\dir" to "B:\dir".
5874 */
5875 else if (len > 3
5876 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5877 && full_path[1] == ':'
5878 && vim_ispathsep(full_path[2]))
5879 p = full_path + 2;
5880#endif
5881 else
5882 p = NULL;
5883 return p;
5884}
5885
5886/*
5887 * Shorten filenames for all buffers.
5888 * When "force" is TRUE: Use full path from now on for files currently being
5889 * edited, both for file name and swap file name. Try to shorten the file
5890 * names a bit, if safe to do so.
5891 * When "force" is FALSE: Only try to shorten absolute file names.
5892 * For buffers that have buftype "nofile" or "scratch": never change the file
5893 * name.
5894 */
5895 void
5896shorten_fnames(force)
5897 int force;
5898{
5899 char_u dirname[MAXPATHL];
5900 buf_T *buf;
5901 char_u *p;
5902
5903 mch_dirname(dirname, MAXPATHL);
5904 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5905 {
5906 if (buf->b_fname != NULL
5907#ifdef FEAT_QUICKFIX
5908 && !bt_nofile(buf)
5909#endif
5910 && !path_with_url(buf->b_fname)
5911 && (force
5912 || buf->b_sfname == NULL
5913 || mch_isFullName(buf->b_sfname)))
5914 {
5915 vim_free(buf->b_sfname);
5916 buf->b_sfname = NULL;
5917 p = shorten_fname(buf->b_ffname, dirname);
5918 if (p != NULL)
5919 {
5920 buf->b_sfname = vim_strsave(p);
5921 buf->b_fname = buf->b_sfname;
5922 }
5923 if (p == NULL || buf->b_fname == NULL)
5924 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005925 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005926
5927 /* Always make the swap file name a full path, a "nofile" buffer may
5928 * also have a swap file. */
5929 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005930 }
5931#ifdef FEAT_WINDOWS
5932 status_redraw_all();
Bram Moolenaar49d7bf12006-02-17 21:45:41 +00005933 redraw_tabline = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005934#endif
5935}
5936
5937#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5938 || defined(FEAT_GUI_MSWIN) \
5939 || defined(FEAT_GUI_MAC) \
5940 || defined(PROTO)
5941/*
5942 * Shorten all filenames in "fnames[count]" by current directory.
5943 */
5944 void
5945shorten_filenames(fnames, count)
5946 char_u **fnames;
5947 int count;
5948{
5949 int i;
5950 char_u dirname[MAXPATHL];
5951 char_u *p;
5952
5953 if (fnames == NULL || count < 1)
5954 return;
5955 mch_dirname(dirname, sizeof(dirname));
5956 for (i = 0; i < count; ++i)
5957 {
5958 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5959 {
5960 /* shorten_fname() returns pointer in given "fnames[i]". If free
5961 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5962 * "p" first then free fnames[i]. */
5963 p = vim_strsave(p);
5964 vim_free(fnames[i]);
5965 fnames[i] = p;
5966 }
5967 }
5968}
5969#endif
5970
5971/*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00005972 * add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
Bram Moolenaar071d4272004-06-13 20:20:40 +00005973 * fo_o_h.ext for MSDOS or when shortname option set.
5974 *
5975 * Assumed that fname is a valid name found in the filesystem we assure that
5976 * the return value is a different name and ends in 'ext'.
5977 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5978 * characters otherwise.
5979 * Space for the returned name is allocated, must be freed later.
5980 * Returns NULL when out of memory.
5981 */
5982 char_u *
5983modname(fname, ext, prepend_dot)
5984 char_u *fname, *ext;
5985 int prepend_dot; /* may prepend a '.' to file name */
5986{
5987 return buf_modname(
5988#ifdef SHORT_FNAME
5989 TRUE,
5990#else
5991 (curbuf->b_p_sn || curbuf->b_shortname),
5992#endif
5993 fname, ext, prepend_dot);
5994}
5995
5996 char_u *
5997buf_modname(shortname, fname, ext, prepend_dot)
5998 int shortname; /* use 8.3 file name */
5999 char_u *fname, *ext;
6000 int prepend_dot; /* may prepend a '.' to file name */
6001{
6002 char_u *retval;
6003 char_u *s;
6004 char_u *e;
6005 char_u *ptr;
6006 int fnamelen, extlen;
6007
6008 extlen = (int)STRLEN(ext);
6009
6010 /*
6011 * If there is no file name we must get the name of the current directory
6012 * (we need the full path in case :cd is used).
6013 */
6014 if (fname == NULL || *fname == NUL)
6015 {
6016 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
6017 if (retval == NULL)
6018 return NULL;
6019 if (mch_dirname(retval, MAXPATHL) == FAIL ||
6020 (fnamelen = (int)STRLEN(retval)) == 0)
6021 {
6022 vim_free(retval);
6023 return NULL;
6024 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006025 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006026 {
6027 retval[fnamelen++] = PATHSEP;
6028 retval[fnamelen] = NUL;
6029 }
6030#ifndef SHORT_FNAME
6031 prepend_dot = FALSE; /* nothing to prepend a dot to */
6032#endif
6033 }
6034 else
6035 {
6036 fnamelen = (int)STRLEN(fname);
6037 retval = alloc((unsigned)(fnamelen + extlen + 3));
6038 if (retval == NULL)
6039 return NULL;
6040 STRCPY(retval, fname);
6041#ifdef VMS
6042 vms_remove_version(retval); /* we do not need versions here */
6043#endif
6044 }
6045
6046 /*
6047 * search backwards until we hit a '/', '\' or ':' replacing all '.'
6048 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
6049 * Then truncate what is after the '/', '\' or ':' to 8 characters for
6050 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
6051 */
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006052 for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006053 {
6054#ifndef RISCOS
6055 if (*ext == '.'
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006056# ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006057 && (!USE_LONG_FNAME || shortname)
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006058# else
6059# ifndef SHORT_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060 && shortname
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006061# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006062# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006063 )
6064 if (*ptr == '.') /* replace '.' by '_' */
6065 *ptr = '_';
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006066#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006067 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006068 {
6069 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006070 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00006071 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006072 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006073
6074 /* the file name has at most BASENAMELEN characters. */
6075#ifndef SHORT_FNAME
6076 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
6077 ptr[BASENAMELEN] = '\0';
6078#endif
6079
6080 s = ptr + STRLEN(ptr);
6081
6082 /*
6083 * For 8.3 file names we may have to reduce the length.
6084 */
6085#ifdef USE_LONG_FNAME
6086 if (!USE_LONG_FNAME || shortname)
6087#else
6088# ifndef SHORT_FNAME
6089 if (shortname)
6090# endif
6091#endif
6092 {
6093 /*
6094 * If there is no file name, or the file name ends in '/', and the
6095 * extension starts with '.', put a '_' before the dot, because just
6096 * ".ext" is invalid.
6097 */
6098 if (fname == NULL || *fname == NUL
6099 || vim_ispathsep(fname[STRLEN(fname) - 1]))
6100 {
6101#ifdef RISCOS
6102 if (*ext == '/')
6103#else
6104 if (*ext == '.')
6105#endif
6106 *s++ = '_';
6107 }
6108 /*
6109 * If the extension starts with '.', truncate the base name at 8
6110 * characters
6111 */
6112#ifdef RISCOS
6113 /* We normally use '/', but swap files are '_' */
6114 else if (*ext == '/' || *ext == '_')
6115#else
6116 else if (*ext == '.')
6117#endif
6118 {
Bram Moolenaar78a15312009-05-15 19:33:18 +00006119 if ((size_t)(s - ptr) > (size_t)8)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006120 {
6121 s = ptr + 8;
6122 *s = '\0';
6123 }
6124 }
6125 /*
6126 * If the extension doesn't start with '.', and the file name
6127 * doesn't have an extension yet, append a '.'
6128 */
6129#ifdef RISCOS
6130 else if ((e = vim_strchr(ptr, '/')) == NULL)
6131 *s++ = '/';
6132#else
6133 else if ((e = vim_strchr(ptr, '.')) == NULL)
6134 *s++ = '.';
6135#endif
6136 /*
6137 * If the extension doesn't start with '.', and there already is an
Bram Moolenaar7263a772007-05-10 17:35:54 +00006138 * extension, it may need to be truncated
Bram Moolenaar071d4272004-06-13 20:20:40 +00006139 */
6140 else if ((int)STRLEN(e) + extlen > 4)
6141 s = e + 4 - extlen;
6142 }
6143#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
6144 /*
6145 * If there is no file name, and the extension starts with '.', put a
6146 * '_' before the dot, because just ".ext" may be invalid if it's on a
6147 * FAT partition, and on HPFS it doesn't matter.
6148 */
6149 else if ((fname == NULL || *fname == NUL) && *ext == '.')
6150 *s++ = '_';
6151#endif
6152
6153 /*
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006154 * Append the extension.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006155 * ext can start with '.' and cannot exceed 3 more characters.
6156 */
6157 STRCPY(s, ext);
6158
6159#ifndef SHORT_FNAME
6160 /*
6161 * Prepend the dot.
6162 */
6163 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
6164#ifdef RISCOS
6165 '/'
6166#else
6167 '.'
6168#endif
6169#ifdef USE_LONG_FNAME
6170 && USE_LONG_FNAME
6171#endif
6172 )
6173 {
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006174 STRMOVE(e + 1, e);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006175#ifdef RISCOS
6176 *e = '/';
6177#else
6178 *e = '.';
6179#endif
6180 }
6181#endif
6182
6183 /*
6184 * Check that, after appending the extension, the file name is really
6185 * different.
6186 */
6187 if (fname != NULL && STRCMP(fname, retval) == 0)
6188 {
6189 /* we search for a character that can be replaced by '_' */
6190 while (--s >= ptr)
6191 {
6192 if (*s != '_')
6193 {
6194 *s = '_';
6195 break;
6196 }
6197 }
6198 if (s < ptr) /* fname was "________.<ext>", how tricky! */
6199 *ptr = 'v';
6200 }
6201 return retval;
6202}
6203
6204/*
6205 * Like fgets(), but if the file line is too long, it is truncated and the
6206 * rest of the line is thrown away. Returns TRUE for end-of-file.
6207 */
6208 int
6209vim_fgets(buf, size, fp)
6210 char_u *buf;
6211 int size;
6212 FILE *fp;
6213{
6214 char *eof;
6215#define FGETS_SIZE 200
6216 char tbuf[FGETS_SIZE];
6217
6218 buf[size - 2] = NUL;
6219#ifdef USE_CR
6220 eof = fgets_cr((char *)buf, size, fp);
6221#else
6222 eof = fgets((char *)buf, size, fp);
6223#endif
6224 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
6225 {
6226 buf[size - 1] = NUL; /* Truncate the line */
6227
6228 /* Now throw away the rest of the line: */
6229 do
6230 {
6231 tbuf[FGETS_SIZE - 2] = NUL;
6232#ifdef USE_CR
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006233 ignoredp = fgets_cr((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006234#else
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006235 ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006236#endif
6237 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
6238 }
6239 return (eof == NULL);
6240}
6241
6242#if defined(USE_CR) || defined(PROTO)
6243/*
6244 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
6245 * Returns TRUE for end-of-file.
6246 * Only used for the Mac, because it's much slower than vim_fgets().
6247 */
6248 int
6249tag_fgets(buf, size, fp)
6250 char_u *buf;
6251 int size;
6252 FILE *fp;
6253{
6254 int i = 0;
6255 int c;
6256 int eof = FALSE;
6257
6258 for (;;)
6259 {
6260 c = fgetc(fp);
6261 if (c == EOF)
6262 {
6263 eof = TRUE;
6264 break;
6265 }
6266 if (c == '\r')
6267 {
6268 /* Always store a NL for end-of-line. */
6269 if (i < size - 1)
6270 buf[i++] = '\n';
6271 c = fgetc(fp);
6272 if (c != '\n') /* Macintosh format: single CR. */
6273 ungetc(c, fp);
6274 break;
6275 }
6276 if (i < size - 1)
6277 buf[i++] = c;
6278 if (c == '\n')
6279 break;
6280 }
6281 buf[i] = NUL;
6282 return eof;
6283}
6284#endif
6285
6286/*
6287 * rename() only works if both files are on the same file system, this
6288 * function will (attempts to?) copy the file across if rename fails -- webb
6289 * Return -1 for failure, 0 for success.
6290 */
6291 int
6292vim_rename(from, to)
6293 char_u *from;
6294 char_u *to;
6295{
6296 int fd_in;
6297 int fd_out;
6298 int n;
6299 char *errmsg = NULL;
6300 char *buffer;
6301#ifdef AMIGA
6302 BPTR flock;
6303#endif
6304 struct stat st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006305 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006306#ifdef HAVE_ACL
6307 vim_acl_T acl; /* ACL from original file */
6308#endif
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006309#if defined(UNIX) || defined(CASE_INSENSITIVE_FILENAME)
6310 int use_tmp_file = FALSE;
6311#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006312
6313 /*
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006314 * When the names are identical, there is nothing to do. When they refer
6315 * to the same file (ignoring case and slash/backslash differences) but
6316 * the file name differs we need to go through a temp file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006317 */
6318 if (fnamecmp(from, to) == 0)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006319 {
6320#ifdef CASE_INSENSITIVE_FILENAME
6321 if (STRCMP(gettail(from), gettail(to)) != 0)
6322 use_tmp_file = TRUE;
6323 else
6324#endif
6325 return 0;
6326 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006327
6328 /*
6329 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
6330 */
6331 if (mch_stat((char *)from, &st) < 0)
6332 return -1;
6333
Bram Moolenaar3576da72008-12-30 15:15:57 +00006334#ifdef UNIX
6335 {
6336 struct stat st_to;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006337
6338 /* It's possible for the source and destination to be the same file.
6339 * This happens when "from" and "to" differ in case and are on a FAT32
6340 * filesystem. In that case go through a temp file name. */
6341 if (mch_stat((char *)to, &st_to) >= 0
6342 && st.st_dev == st_to.st_dev
6343 && st.st_ino == st_to.st_ino)
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006344 use_tmp_file = TRUE;
6345 }
6346#endif
6347
6348#if defined(UNIX) || defined(CASE_INSENSITIVE_FILENAME)
6349 if (use_tmp_file)
6350 {
6351 char tempname[MAXPATHL + 1];
6352
6353 /*
6354 * Find a name that doesn't exist and is in the same directory.
6355 * Rename "from" to "tempname" and then rename "tempname" to "to".
6356 */
6357 if (STRLEN(from) >= MAXPATHL - 5)
6358 return -1;
6359 STRCPY(tempname, from);
6360 for (n = 123; n < 99999; ++n)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006361 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006362 sprintf((char *)gettail((char_u *)tempname), "%d", n);
6363 if (mch_stat(tempname, &st) < 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006364 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006365 if (mch_rename((char *)from, tempname) == 0)
Bram Moolenaar3576da72008-12-30 15:15:57 +00006366 {
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006367 if (mch_rename(tempname, (char *)to) == 0)
6368 return 0;
6369 /* Strange, the second step failed. Try moving the
6370 * file back and return failure. */
6371 mch_rename(tempname, (char *)from);
Bram Moolenaar3576da72008-12-30 15:15:57 +00006372 return -1;
6373 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006374 /* If it fails for one temp name it will most likely fail
6375 * for any temp name, give up. */
6376 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006377 }
Bram Moolenaar3576da72008-12-30 15:15:57 +00006378 }
Bram Moolenaare0e6f992008-12-31 15:21:32 +00006379 return -1;
Bram Moolenaar3576da72008-12-30 15:15:57 +00006380 }
6381#endif
6382
Bram Moolenaar071d4272004-06-13 20:20:40 +00006383 /*
6384 * Delete the "to" file, this is required on some systems to make the
6385 * mch_rename() work, on other systems it makes sure that we don't have
6386 * two files when the mch_rename() fails.
6387 */
6388
6389#ifdef AMIGA
6390 /*
6391 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
6392 * that the name of the "to" file is the same as the "from" file, even
Bram Moolenaar7263a772007-05-10 17:35:54 +00006393 * though the names are different. To avoid the chance of accidentally
Bram Moolenaar071d4272004-06-13 20:20:40 +00006394 * deleting the "from" file (horror!) we lock it during the remove.
6395 *
6396 * When used for making a backup before writing the file: This should not
6397 * happen with ":w", because startscript() should detect this problem and
6398 * set buf->b_shortname, causing modname() to return a correct ".bak" file
6399 * name. This problem does exist with ":w filename", but then the
6400 * original file will be somewhere else so the backup isn't really
6401 * important. If autoscripting is off the rename may fail.
6402 */
6403 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
6404#endif
6405 mch_remove(to);
6406#ifdef AMIGA
6407 if (flock)
6408 UnLock(flock);
6409#endif
6410
6411 /*
6412 * First try a normal rename, return if it works.
6413 */
6414 if (mch_rename((char *)from, (char *)to) == 0)
6415 return 0;
6416
6417 /*
6418 * Rename() failed, try copying the file.
6419 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006420 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006421#ifdef HAVE_ACL
6422 /* For systems that support ACL: get the ACL from the original file. */
6423 acl = mch_get_acl(from);
6424#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006425 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
6426 if (fd_in == -1)
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006427 {
6428#ifdef HAVE_ACL
6429 mch_free_acl(acl);
6430#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006431 return -1;
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006432 }
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006433
6434 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00006435 fd_out = mch_open((char *)to,
6436 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006437 if (fd_out == -1)
6438 {
6439 close(fd_in);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006440#ifdef HAVE_ACL
6441 mch_free_acl(acl);
6442#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006443 return -1;
6444 }
6445
6446 buffer = (char *)alloc(BUFSIZE);
6447 if (buffer == NULL)
6448 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006449 close(fd_out);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006450 close(fd_in);
6451#ifdef HAVE_ACL
6452 mch_free_acl(acl);
6453#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006454 return -1;
6455 }
6456
6457 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
6458 if (vim_write(fd_out, buffer, n) != n)
6459 {
6460 errmsg = _("E208: Error writing to \"%s\"");
6461 break;
6462 }
6463
6464 vim_free(buffer);
6465 close(fd_in);
6466 if (close(fd_out) < 0)
6467 errmsg = _("E209: Error closing \"%s\"");
6468 if (n < 0)
6469 {
6470 errmsg = _("E210: Error reading \"%s\"");
6471 to = from;
6472 }
Bram Moolenaar7263a772007-05-10 17:35:54 +00006473#ifndef UNIX /* for Unix mch_open() already set the permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006474 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00006475#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006476#ifdef HAVE_ACL
6477 mch_set_acl(to, acl);
Bram Moolenaarb23a7e82008-06-27 18:42:32 +00006478 mch_free_acl(acl);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006479#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006480 if (errmsg != NULL)
6481 {
6482 EMSG2(errmsg, to);
6483 return -1;
6484 }
6485 mch_remove(from);
6486 return 0;
6487}
6488
6489static int already_warned = FALSE;
6490
6491/*
6492 * Check if any not hidden buffer has been changed.
6493 * Postpone the check if there are characters in the stuff buffer, a global
6494 * command is being executed, a mapping is being executed or an autocommand is
6495 * busy.
6496 * Returns TRUE if some message was written (screen should be redrawn and
6497 * cursor positioned).
6498 */
6499 int
6500check_timestamps(focus)
6501 int focus; /* called for GUI focus event */
6502{
6503 buf_T *buf;
6504 int didit = 0;
6505 int n;
6506
6507 /* Don't check timestamps while system() or another low-level function may
6508 * cause us to lose and gain focus. */
6509 if (no_check_timestamps > 0)
6510 return FALSE;
6511
6512 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6513 * event and we would keep on checking if the file is steadily growing.
6514 * Do check again after typing something. */
6515 if (focus && did_check_timestamps)
6516 {
6517 need_check_timestamps = TRUE;
6518 return FALSE;
6519 }
6520
6521 if (!stuff_empty() || global_busy || !typebuf_typed()
6522#ifdef FEAT_AUTOCMD
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006523 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006524#endif
6525 )
6526 need_check_timestamps = TRUE; /* check later */
6527 else
6528 {
6529 ++no_wait_return;
6530 did_check_timestamps = TRUE;
6531 already_warned = FALSE;
6532 for (buf = firstbuf; buf != NULL; )
6533 {
6534 /* Only check buffers in a window. */
6535 if (buf->b_nwindows > 0)
6536 {
6537 n = buf_check_timestamp(buf, focus);
6538 if (didit < n)
6539 didit = n;
6540 if (n > 0 && !buf_valid(buf))
6541 {
6542 /* Autocommands have removed the buffer, start at the
6543 * first one again. */
6544 buf = firstbuf;
6545 continue;
6546 }
6547 }
6548 buf = buf->b_next;
6549 }
6550 --no_wait_return;
6551 need_check_timestamps = FALSE;
6552 if (need_wait_return && didit == 2)
6553 {
6554 /* make sure msg isn't overwritten */
6555 msg_puts((char_u *)"\n");
6556 out_flush();
6557 }
6558 }
6559 return didit;
6560}
6561
6562/*
6563 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6564 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6565 * empty.
6566 */
6567 static int
6568move_lines(frombuf, tobuf)
6569 buf_T *frombuf;
6570 buf_T *tobuf;
6571{
6572 buf_T *tbuf = curbuf;
6573 int retval = OK;
6574 linenr_T lnum;
6575 char_u *p;
6576
6577 /* Copy the lines in "frombuf" to "tobuf". */
6578 curbuf = tobuf;
6579 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6580 {
6581 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6582 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6583 {
6584 vim_free(p);
6585 retval = FAIL;
6586 break;
6587 }
6588 vim_free(p);
6589 }
6590
6591 /* Delete all the lines in "frombuf". */
6592 if (retval != FAIL)
6593 {
6594 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006595 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6596 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006597 {
6598 /* Oops! We could try putting back the saved lines, but that
6599 * might fail again... */
6600 retval = FAIL;
6601 break;
6602 }
6603 }
6604
6605 curbuf = tbuf;
6606 return retval;
6607}
6608
6609/*
6610 * Check if buffer "buf" has been changed.
6611 * Also check if the file for a new buffer unexpectedly appeared.
6612 * return 1 if a changed buffer was found.
6613 * return 2 if a message has been displayed.
6614 * return 0 otherwise.
6615 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006616 int
6617buf_check_timestamp(buf, focus)
6618 buf_T *buf;
Bram Moolenaar78a15312009-05-15 19:33:18 +00006619 int focus UNUSED; /* called for GUI focus event */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006620{
6621 struct stat st;
6622 int stat_res;
6623 int retval = 0;
6624 char_u *path;
6625 char_u *tbuf;
6626 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006627 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006628 int helpmesg = FALSE;
6629 int reload = FALSE;
6630#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6631 int can_reload = FALSE;
6632#endif
6633 size_t orig_size = buf->b_orig_size;
6634 int orig_mode = buf->b_orig_mode;
6635#ifdef FEAT_GUI
6636 int save_mouse_correct = need_mouse_correct;
6637#endif
6638#ifdef FEAT_AUTOCMD
6639 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006640 int n;
6641 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006642#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006643 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006644
6645 /* If there is no file name, the buffer is not loaded, 'buftype' is
6646 * set, we are in the middle of a save or being called recursively: ignore
6647 * this buffer. */
6648 if (buf->b_ffname == NULL
6649 || buf->b_ml.ml_mfp == NULL
6650#if defined(FEAT_QUICKFIX)
6651 || *buf->b_p_bt != NUL
6652#endif
6653 || buf->b_saving
6654#ifdef FEAT_AUTOCMD
6655 || busy
6656#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006657#ifdef FEAT_NETBEANS_INTG
6658 || isNetbeansBuffer(buf)
6659#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006660 )
6661 return 0;
6662
6663 if ( !(buf->b_flags & BF_NOTEDITED)
6664 && buf->b_mtime != 0
6665 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6666 || time_differs((long)st.st_mtime, buf->b_mtime)
6667#ifdef HAVE_ST_MODE
6668 || (int)st.st_mode != buf->b_orig_mode
6669#else
6670 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6671#endif
6672 ))
6673 {
6674 retval = 1;
6675
Bram Moolenaar316059c2006-01-14 21:18:42 +00006676 /* set b_mtime to stop further warnings (e.g., when executing
6677 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006678 if (stat_res < 0)
6679 {
6680 buf->b_mtime = 0;
6681 buf->b_orig_size = 0;
6682 buf->b_orig_mode = 0;
6683 }
6684 else
6685 buf_store_time(buf, &st, buf->b_ffname);
6686
6687 /* Don't do anything for a directory. Might contain the file
6688 * explorer. */
6689 if (mch_isdir(buf->b_fname))
6690 ;
6691
6692 /*
6693 * If 'autoread' is set, the buffer has no changes and the file still
6694 * exists, reload the buffer. Use the buffer-local option value if it
6695 * was set, the global option value otherwise.
6696 */
6697 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6698 && !bufIsChanged(buf) && stat_res >= 0)
6699 reload = TRUE;
6700 else
6701 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006702 if (stat_res < 0)
6703 reason = "deleted";
6704 else if (bufIsChanged(buf))
6705 reason = "conflict";
6706 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6707 reason = "changed";
6708 else if (orig_mode != buf->b_orig_mode)
6709 reason = "mode";
6710 else
6711 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006712
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006713#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006714 /*
6715 * Only give the warning if there are no FileChangedShell
6716 * autocommands.
6717 * Avoid being called recursively by setting "busy".
6718 */
6719 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006720# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006721 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6722 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006723# endif
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006724 ++allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006725 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6726 buf->b_fname, buf->b_fname, FALSE, buf);
Bram Moolenaarbf1b7a72009-03-05 02:15:53 +00006727 --allbuf_lock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006728 busy = FALSE;
6729 if (n)
6730 {
6731 if (!buf_valid(buf))
6732 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006733# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006734 s = get_vim_var_str(VV_FCS_CHOICE);
6735 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6736 reload = TRUE;
6737 else if (STRCMP(s, "ask") == 0)
6738 n = FALSE;
6739 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006740# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006741 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006742 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006743 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006744#endif
6745 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006746 if (*reason == 'd')
6747 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006748 else
6749 {
6750 helpmesg = TRUE;
6751#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6752 can_reload = TRUE;
6753#endif
6754 /*
6755 * Check if the file contents really changed to avoid
6756 * giving a warning when only the timestamp was set (e.g.,
6757 * checked out of CVS). Always warn when the buffer was
6758 * changed.
6759 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006760 if (reason[2] == 'n')
6761 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006762 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006763 mesg2 = _("See \":help W12\" for more info.");
6764 }
6765 else if (reason[1] == 'h')
6766 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006767 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006768 mesg2 = _("See \":help W11\" for more info.");
6769 }
6770 else if (*reason == 'm')
6771 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006772 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006773 mesg2 = _("See \":help W16\" for more info.");
6774 }
Bram Moolenaar85388b52009-06-24 09:58:32 +00006775 else
6776 /* Only timestamp changed, store it to avoid a warning
6777 * in check_mtime() later. */
6778 buf->b_mtime_read = buf->b_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006779 }
6780 }
6781 }
6782
6783 }
6784 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6785 && vim_fexists(buf->b_ffname))
6786 {
6787 retval = 1;
6788 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6789 buf->b_flags |= BF_NEW_W;
6790#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6791 can_reload = TRUE;
6792#endif
6793 }
6794
6795 if (mesg != NULL)
6796 {
6797 path = home_replace_save(buf, buf->b_fname);
6798 if (path != NULL)
6799 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006800 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006801 mesg2 = "";
6802 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6803 + STRLEN(mesg2) + 2));
6804 sprintf((char *)tbuf, mesg, path);
Bram Moolenaar496c5262009-03-18 14:42:00 +00006805#ifdef FEAT_EVAL
6806 /* Set warningmsg here, before the unimportant and output-specific
6807 * mesg2 has been appended. */
6808 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
6809#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006810#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6811 if (can_reload)
6812 {
6813 if (*mesg2 != NUL)
6814 {
6815 STRCAT(tbuf, "\n");
6816 STRCAT(tbuf, mesg2);
6817 }
6818 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6819 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6820 reload = TRUE;
6821 }
6822 else
6823#endif
6824 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6825 {
6826 if (*mesg2 != NUL)
6827 {
6828 STRCAT(tbuf, "; ");
6829 STRCAT(tbuf, mesg2);
6830 }
6831 EMSG(tbuf);
6832 retval = 2;
6833 }
6834 else
6835 {
Bram Moolenaared203462004-06-16 11:19:22 +00006836# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006837 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006838# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006839 {
6840 msg_start();
6841 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6842 if (*mesg2 != NUL)
6843 msg_puts_attr((char_u *)mesg2,
6844 hl_attr(HLF_W) + MSG_HIST);
6845 msg_clr_eos();
6846 (void)msg_end();
6847 if (emsg_silent == 0)
6848 {
6849 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006850# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006851 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006852# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006853 /* give the user some time to think about it */
6854 ui_delay(1000L, TRUE);
6855
6856 /* don't redraw and erase the message */
6857 redraw_cmdline = FALSE;
6858 }
6859 }
6860 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006861 }
6862
6863 vim_free(path);
6864 vim_free(tbuf);
6865 }
6866 }
6867
6868 if (reload)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006869 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00006870 buf_reload(buf, orig_mode);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006871
Bram Moolenaar56718732006-03-15 22:53:57 +00006872#ifdef FEAT_AUTOCMD
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006873 /* Trigger FileChangedShell when the file was changed in any way. */
6874 if (buf_valid(buf) && retval != 0)
Bram Moolenaar56718732006-03-15 22:53:57 +00006875 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
6876 buf->b_fname, buf->b_fname, FALSE, buf);
6877#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006878#ifdef FEAT_GUI
6879 /* restore this in case an autocommand has set it; it would break
6880 * 'mousefocus' */
6881 need_mouse_correct = save_mouse_correct;
6882#endif
6883
6884 return retval;
6885}
6886
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006887/*
6888 * Reload a buffer that is already loaded.
6889 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00006890 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
6891 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006892 */
6893 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00006894buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006895 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00006896 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006897{
6898 exarg_T ea;
6899 pos_T old_cursor;
6900 linenr_T old_topline;
6901 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006902 buf_T *savebuf;
6903 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006904 aco_save_T aco;
6905
6906 /* set curwin/curbuf for "buf" and save some things */
6907 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006908
6909 /* We only want to read the text from the file, not reset the syntax
6910 * highlighting, clear marks, diff status, etc. Force the fileformat
6911 * and encoding to be the same. */
6912 if (prep_exarg(&ea, buf) == OK)
6913 {
6914 old_cursor = curwin->w_cursor;
6915 old_topline = curwin->w_topline;
6916
6917 /*
6918 * To behave like when a new file is edited (matters for
6919 * BufReadPost autocommands) we first need to delete the current
6920 * buffer contents. But if reading the file fails we should keep
6921 * the old contents. Can't use memory only, the file might be
6922 * too big. Use a hidden buffer to move the buffer contents to.
6923 */
6924 if (bufempty())
6925 savebuf = NULL;
6926 else
6927 {
6928 /* Allocate a buffer without putting it in the buffer list. */
6929 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006930 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006931 {
6932 /* Open the memline. */
6933 curbuf = savebuf;
6934 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00006935 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006936 curbuf = buf;
6937 curwin->w_buffer = buf;
6938 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006939 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006940 || move_lines(buf, savebuf) == FAIL)
6941 {
6942 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6943 buf->b_fname);
6944 saved = FAIL;
6945 }
6946 }
6947
6948 if (saved == OK)
6949 {
6950 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6951#ifdef FEAT_AUTOCMD
6952 keep_filetype = TRUE; /* don't detect 'filetype' */
6953#endif
6954 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6955 (linenr_T)0,
6956 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6957 {
6958#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6959 if (!aborting())
6960#endif
6961 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006962 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006963 {
6964 /* Put the text back from the save buffer. First
6965 * delete any lines that readfile() added. */
6966 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00006967 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006968 break;
6969 (void)move_lines(savebuf, buf);
6970 }
6971 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006972 else if (buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006973 {
6974 /* Mark the buffer as unmodified and free undo info. */
6975 unchanged(buf, TRUE);
6976 u_blockfree(buf);
6977 u_clearall(buf);
6978 }
6979 }
6980 vim_free(ea.cmd);
6981
Bram Moolenaar8424a622006-04-19 21:23:36 +00006982 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006983 wipe_buffer(savebuf, FALSE);
6984
6985#ifdef FEAT_DIFF
6986 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00006987 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006988#endif
6989
6990 /* Restore the topline and cursor position and check it (lines may
6991 * have been removed). */
6992 if (old_topline > curbuf->b_ml.ml_line_count)
6993 curwin->w_topline = curbuf->b_ml.ml_line_count;
6994 else
6995 curwin->w_topline = old_topline;
6996 curwin->w_cursor = old_cursor;
6997 check_cursor();
6998 update_topline();
6999#ifdef FEAT_AUTOCMD
7000 keep_filetype = FALSE;
7001#endif
7002#ifdef FEAT_FOLDING
7003 {
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007004 win_T *wp;
7005 tabpage_T *tp;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007006
7007 /* Update folds unless they are defined manually. */
Bram Moolenaarbd1e5d22009-04-29 09:02:44 +00007008 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007009 if (wp->w_buffer == curwin->w_buffer
7010 && !foldmethodIsManual(wp))
7011 foldUpdateAll(wp);
7012 }
7013#endif
7014 /* If the mode didn't change and 'readonly' was set, keep the old
7015 * value; the user probably used the ":view" command. But don't
7016 * reset it, might have had a read error. */
7017 if (orig_mode == curbuf->b_orig_mode)
7018 curbuf->b_p_ro |= old_ro;
7019 }
7020
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007021 /* restore curwin/curbuf and a few other things */
7022 aucmd_restbuf(&aco);
7023 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00007024}
7025
Bram Moolenaar071d4272004-06-13 20:20:40 +00007026 void
7027buf_store_time(buf, st, fname)
7028 buf_T *buf;
7029 struct stat *st;
Bram Moolenaar78a15312009-05-15 19:33:18 +00007030 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007031{
7032 buf->b_mtime = (long)st->st_mtime;
7033 buf->b_orig_size = (size_t)st->st_size;
7034#ifdef HAVE_ST_MODE
7035 buf->b_orig_mode = (int)st->st_mode;
7036#else
7037 buf->b_orig_mode = mch_getperm(fname);
7038#endif
7039}
7040
7041/*
7042 * Adjust the line with missing eol, used for the next write.
7043 * Used for do_filter(), when the input lines for the filter are deleted.
7044 */
7045 void
7046write_lnum_adjust(offset)
7047 linenr_T offset;
7048{
Bram Moolenaardf177f62005-02-22 08:39:57 +00007049 if (write_no_eol_lnum != 0) /* only if there is a missing eol */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007050 write_no_eol_lnum += offset;
7051}
7052
7053#if defined(TEMPDIRNAMES) || defined(PROTO)
7054static long temp_count = 0; /* Temp filename counter. */
7055
7056/*
7057 * Delete the temp directory and all files it contains.
7058 */
7059 void
7060vim_deltempdir()
7061{
7062 char_u **files;
7063 int file_count;
7064 int i;
7065
7066 if (vim_tempdir != NULL)
7067 {
7068 sprintf((char *)NameBuff, "%s*", vim_tempdir);
7069 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
7070 EW_DIR|EW_FILE|EW_SILENT) == OK)
7071 {
7072 for (i = 0; i < file_count; ++i)
7073 mch_remove(files[i]);
7074 FreeWild(file_count, files);
7075 }
7076 gettail(NameBuff)[-1] = NUL;
7077 (void)mch_rmdir(NameBuff);
7078
7079 vim_free(vim_tempdir);
7080 vim_tempdir = NULL;
7081 }
7082}
7083#endif
7084
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007085#ifdef TEMPDIRNAMES
Bram Moolenaar071d4272004-06-13 20:20:40 +00007086/*
Bram Moolenaareaf03392009-11-17 11:08:52 +00007087 * Directory "tempdir" was created. Expand this name to a full path and put
7088 * it in "vim_tempdir". This avoids that using ":cd" would confuse us.
7089 * "tempdir" must be no longer than MAXPATHL.
7090 */
7091 static void
7092vim_settempdir(tempdir)
7093 char_u *tempdir;
7094{
7095 char_u *buf;
7096
7097 buf = alloc((unsigned)MAXPATHL + 2);
7098 if (buf != NULL)
7099 {
7100 if (vim_FullName(tempdir, buf, MAXPATHL, FALSE) == FAIL)
7101 STRCPY(buf, tempdir);
7102# ifdef __EMX__
7103 if (vim_strchr(buf, '/') != NULL)
7104 STRCAT(buf, "/");
7105 else
7106# endif
7107 add_pathsep(buf);
7108 vim_tempdir = vim_strsave(buf);
7109 vim_free(buf);
7110 }
7111}
Bram Moolenaar4592dee2009-11-18 19:11:58 +00007112#endif
Bram Moolenaareaf03392009-11-17 11:08:52 +00007113
7114/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007115 * vim_tempname(): Return a unique name that can be used for a temp file.
7116 *
7117 * The temp file is NOT created.
7118 *
7119 * The returned pointer is to allocated memory.
7120 * The returned pointer is NULL if no valid name was found.
7121 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007122 char_u *
7123vim_tempname(extra_char)
Bram Moolenaar78a15312009-05-15 19:33:18 +00007124 int extra_char UNUSED; /* char to use in the name instead of '?' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007125{
7126#ifdef USE_TMPNAM
7127 char_u itmp[L_tmpnam]; /* use tmpnam() */
7128#else
7129 char_u itmp[TEMPNAMELEN];
7130#endif
7131
7132#ifdef TEMPDIRNAMES
7133 static char *(tempdirs[]) = {TEMPDIRNAMES};
7134 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007135# ifndef EEXIST
7136 struct stat st;
7137# endif
7138
7139 /*
7140 * This will create a directory for private use by this instance of Vim.
7141 * This is done once, and the same directory is used for all temp files.
7142 * This method avoids security problems because of symlink attacks et al.
7143 * It's also a bit faster, because we only need to check for an existing
7144 * file when creating the directory and not for each temp file.
7145 */
7146 if (vim_tempdir == NULL)
7147 {
7148 /*
7149 * Try the entries in TEMPDIRNAMES to create the temp directory.
7150 */
Bram Moolenaar78a15312009-05-15 19:33:18 +00007151 for (i = 0; i < (int)(sizeof(tempdirs) / sizeof(char *)); ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007152 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007153# ifndef HAVE_MKDTEMP
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007154 size_t itmplen;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007155 long nr;
7156 long off;
7157# endif
7158
Bram Moolenaar071d4272004-06-13 20:20:40 +00007159 /* expand $TMP, leave room for "/v1100000/999999999" */
7160 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
7161 if (mch_isdir(itmp)) /* directory exists */
7162 {
7163# ifdef __EMX__
7164 /* If $TMP contains a forward slash (perhaps using bash or
7165 * tcsh), don't add a backslash, use a forward slash!
7166 * Adding 2 backslashes didn't work. */
7167 if (vim_strchr(itmp, '/') != NULL)
7168 STRCAT(itmp, "/");
7169 else
7170# endif
7171 add_pathsep(itmp);
7172
Bram Moolenaareaf03392009-11-17 11:08:52 +00007173# ifdef HAVE_MKDTEMP
7174 /* Leave room for filename */
7175 STRCAT(itmp, "vXXXXXX");
7176 if (mkdtemp((char *)itmp) != NULL)
7177 vim_settempdir(itmp);
7178# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007179 /* Get an arbitrary number of up to 6 digits. When it's
7180 * unlikely that it already exists it will be faster,
7181 * otherwise it doesn't matter. The use of mkdir() avoids any
7182 * security problems because of the predictable number. */
7183 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01007184 itmplen = STRLEN(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007185
7186 /* Try up to 10000 different values until we find a name that
7187 * doesn't exist. */
7188 for (off = 0; off < 10000L; ++off)
7189 {
7190 int r;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007191# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007192 mode_t umask_save;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007193# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007194
Bram Moolenaareaf03392009-11-17 11:08:52 +00007195 sprintf((char *)itmp + itmplen, "v%ld", nr + off);
7196# ifndef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007197 /* If mkdir() does not set errno to EEXIST, check for
7198 * existing file here. There is a race condition then,
7199 * although it's fail-safe. */
7200 if (mch_stat((char *)itmp, &st) >= 0)
7201 continue;
Bram Moolenaareaf03392009-11-17 11:08:52 +00007202# endif
7203# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007204 /* Make sure the umask doesn't remove the executable bit.
7205 * "repl" has been reported to use "177". */
7206 umask_save = umask(077);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007207# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007208 r = vim_mkdir(itmp, 0700);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007209# if defined(UNIX) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007210 (void)umask(umask_save);
Bram Moolenaareaf03392009-11-17 11:08:52 +00007211# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007212 if (r == 0)
7213 {
Bram Moolenaareaf03392009-11-17 11:08:52 +00007214 vim_settempdir(itmp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007215 break;
7216 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007217# ifdef EEXIST
Bram Moolenaar071d4272004-06-13 20:20:40 +00007218 /* If the mkdir() didn't fail because the file/dir exists,
7219 * we probably can't create any dir here, try another
7220 * place. */
7221 if (errno != EEXIST)
Bram Moolenaareaf03392009-11-17 11:08:52 +00007222# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007223 break;
7224 }
Bram Moolenaareaf03392009-11-17 11:08:52 +00007225# endif /* HAVE_MKDTEMP */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007226 if (vim_tempdir != NULL)
7227 break;
7228 }
7229 }
7230 }
7231
7232 if (vim_tempdir != NULL)
7233 {
7234 /* There is no need to check if the file exists, because we own the
7235 * directory and nobody else creates a file in it. */
7236 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
7237 return vim_strsave(itmp);
7238 }
7239
7240 return NULL;
7241
7242#else /* TEMPDIRNAMES */
7243
7244# ifdef WIN3264
7245 char szTempFile[_MAX_PATH + 1];
7246 char buf4[4];
7247 char_u *retval;
7248 char_u *p;
7249
7250 STRCPY(itmp, "");
7251 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
7252 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
7253 strcpy(buf4, "VIM");
7254 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
7255 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
7256 return NULL;
7257 /* GetTempFileName() will create the file, we don't want that */
7258 (void)DeleteFile(itmp);
7259
7260 /* Backslashes in a temp file name cause problems when filtering with
7261 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
7262 * didn't set 'shellslash'. */
7263 retval = vim_strsave(itmp);
7264 if (*p_shcf == '-' || p_ssl)
7265 for (p = retval; *p; ++p)
7266 if (*p == '\\')
7267 *p = '/';
7268 return retval;
7269
7270# else /* WIN3264 */
7271
7272# ifdef USE_TMPNAM
7273 /* tmpnam() will make its own name */
7274 if (*tmpnam((char *)itmp) == NUL)
7275 return NULL;
7276# else
7277 char_u *p;
7278
7279# ifdef VMS_TEMPNAM
7280 /* mktemp() is not working on VMS. It seems to be
7281 * a do-nothing function. Therefore we use tempnam().
7282 */
7283 sprintf((char *)itmp, "VIM%c", extra_char);
7284 p = (char_u *)tempnam("tmp:", (char *)itmp);
7285 if (p != NULL)
7286 {
7287 /* VMS will use '.LOG' if we don't explicitly specify an extension,
7288 * and VIM will then be unable to find the file later */
7289 STRCPY(itmp, p);
7290 STRCAT(itmp, ".txt");
7291 free(p);
7292 }
7293 else
7294 return NULL;
7295# else
7296 STRCPY(itmp, TEMPNAME);
7297 if ((p = vim_strchr(itmp, '?')) != NULL)
7298 *p = extra_char;
7299 if (mktemp((char *)itmp) == NULL)
7300 return NULL;
7301# endif
7302# endif
7303
7304 return vim_strsave(itmp);
7305# endif /* WIN3264 */
7306#endif /* TEMPDIRNAMES */
7307}
7308
7309#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
7310/*
7311 * Convert all backslashes in fname to forward slashes in-place.
7312 */
7313 void
7314forward_slash(fname)
7315 char_u *fname;
7316{
7317 char_u *p;
7318
7319 for (p = fname; *p != NUL; ++p)
7320# ifdef FEAT_MBYTE
7321 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007322 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007323 ++p;
7324 else
7325# endif
7326 if (*p == '\\')
7327 *p = '/';
7328}
7329#endif
7330
7331
7332/*
7333 * Code for automatic commands.
7334 *
7335 * Only included when "FEAT_AUTOCMD" has been defined.
7336 */
7337
7338#if defined(FEAT_AUTOCMD) || defined(PROTO)
7339
7340/*
7341 * The autocommands are stored in a list for each event.
7342 * Autocommands for the same pattern, that are consecutive, are joined
7343 * together, to avoid having to match the pattern too often.
7344 * The result is an array of Autopat lists, which point to AutoCmd lists:
7345 *
7346 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
7347 * Autopat.cmds Autopat.cmds
7348 * | |
7349 * V V
7350 * AutoCmd.next AutoCmd.next
7351 * | |
7352 * V V
7353 * AutoCmd.next NULL
7354 * |
7355 * V
7356 * NULL
7357 *
7358 * first_autopat[1] --> Autopat.next --> NULL
7359 * Autopat.cmds
7360 * |
7361 * V
7362 * AutoCmd.next
7363 * |
7364 * V
7365 * NULL
7366 * etc.
7367 *
7368 * The order of AutoCmds is important, this is the order in which they were
7369 * defined and will have to be executed.
7370 */
7371typedef struct AutoCmd
7372{
7373 char_u *cmd; /* The command to be executed (NULL
7374 when command has been removed) */
7375 char nested; /* If autocommands nest here */
7376 char last; /* last command in list */
7377#ifdef FEAT_EVAL
7378 scid_T scriptID; /* script ID where defined */
7379#endif
7380 struct AutoCmd *next; /* Next AutoCmd in list */
7381} AutoCmd;
7382
7383typedef struct AutoPat
7384{
7385 int group; /* group ID */
7386 char_u *pat; /* pattern as typed (NULL when pattern
7387 has been removed) */
7388 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007389 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007390 char allow_dirs; /* Pattern may match whole path */
7391 char last; /* last pattern for apply_autocmds() */
7392 AutoCmd *cmds; /* list of commands to do */
7393 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007394 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007395} AutoPat;
7396
7397static struct event_name
7398{
7399 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007400 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007401} event_names[] =
7402{
7403 {"BufAdd", EVENT_BUFADD},
7404 {"BufCreate", EVENT_BUFADD},
7405 {"BufDelete", EVENT_BUFDELETE},
7406 {"BufEnter", EVENT_BUFENTER},
7407 {"BufFilePost", EVENT_BUFFILEPOST},
7408 {"BufFilePre", EVENT_BUFFILEPRE},
7409 {"BufHidden", EVENT_BUFHIDDEN},
7410 {"BufLeave", EVENT_BUFLEAVE},
7411 {"BufNew", EVENT_BUFNEW},
7412 {"BufNewFile", EVENT_BUFNEWFILE},
7413 {"BufRead", EVENT_BUFREADPOST},
7414 {"BufReadCmd", EVENT_BUFREADCMD},
7415 {"BufReadPost", EVENT_BUFREADPOST},
7416 {"BufReadPre", EVENT_BUFREADPRE},
7417 {"BufUnload", EVENT_BUFUNLOAD},
7418 {"BufWinEnter", EVENT_BUFWINENTER},
7419 {"BufWinLeave", EVENT_BUFWINLEAVE},
7420 {"BufWipeout", EVENT_BUFWIPEOUT},
7421 {"BufWrite", EVENT_BUFWRITEPRE},
7422 {"BufWritePost", EVENT_BUFWRITEPOST},
7423 {"BufWritePre", EVENT_BUFWRITEPRE},
7424 {"BufWriteCmd", EVENT_BUFWRITECMD},
7425 {"CmdwinEnter", EVENT_CMDWINENTER},
7426 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007427 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007428 {"CursorHold", EVENT_CURSORHOLD},
7429 {"CursorHoldI", EVENT_CURSORHOLDI},
7430 {"CursorMoved", EVENT_CURSORMOVED},
7431 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007432 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7433 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007434 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7435 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7436 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7437 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007438 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007439 {"FileChangedRO", EVENT_FILECHANGEDRO},
7440 {"FileReadPost", EVENT_FILEREADPOST},
7441 {"FileReadPre", EVENT_FILEREADPRE},
7442 {"FileReadCmd", EVENT_FILEREADCMD},
7443 {"FileType", EVENT_FILETYPE},
7444 {"FileWritePost", EVENT_FILEWRITEPOST},
7445 {"FileWritePre", EVENT_FILEWRITEPRE},
7446 {"FileWriteCmd", EVENT_FILEWRITECMD},
7447 {"FilterReadPost", EVENT_FILTERREADPOST},
7448 {"FilterReadPre", EVENT_FILTERREADPRE},
7449 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7450 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7451 {"FocusGained", EVENT_FOCUSGAINED},
7452 {"FocusLost", EVENT_FOCUSLOST},
7453 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7454 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007455 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007456 {"InsertChange", EVENT_INSERTCHANGE},
7457 {"InsertEnter", EVENT_INSERTENTER},
7458 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007459 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007460 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7461 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007462 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007463 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007464 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7465 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007466 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007467 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007468 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007469 {"StdinReadPost", EVENT_STDINREADPOST},
7470 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007471 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007472 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007473 {"TabEnter", EVENT_TABENTER},
7474 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007475 {"TermChanged", EVENT_TERMCHANGED},
7476 {"TermResponse", EVENT_TERMRESPONSE},
7477 {"User", EVENT_USER},
7478 {"VimEnter", EVENT_VIMENTER},
7479 {"VimLeave", EVENT_VIMLEAVE},
7480 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7481 {"WinEnter", EVENT_WINENTER},
7482 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007483 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007484 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007485};
7486
7487static AutoPat *first_autopat[NUM_EVENTS] =
7488{
7489 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7490 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7491 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7492 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007493 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7494 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007495};
7496
7497/*
7498 * struct used to keep status while executing autocommands for an event.
7499 */
7500typedef struct AutoPatCmd
7501{
7502 AutoPat *curpat; /* next AutoPat to examine */
7503 AutoCmd *nextcmd; /* next AutoCmd to execute */
7504 int group; /* group being used */
7505 char_u *fname; /* fname to match with */
7506 char_u *sfname; /* sfname to match with */
7507 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007508 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007509 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7510 buf is deleted */
7511 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007512} AutoPatCmd;
7513
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007514static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007515
Bram Moolenaar071d4272004-06-13 20:20:40 +00007516/*
7517 * augroups stores a list of autocmd group names.
7518 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007519static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007520#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7521
7522/*
7523 * The ID of the current group. Group 0 is the default one.
7524 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007525static int current_augroup = AUGROUP_DEFAULT;
7526
7527static int au_need_clean = FALSE; /* need to delete marked patterns */
7528
Bram Moolenaar754b5602006-02-09 23:53:20 +00007529static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007530static void au_remove_pat __ARGS((AutoPat *ap));
7531static void au_remove_cmds __ARGS((AutoPat *ap));
7532static void au_cleanup __ARGS((void));
7533static int au_new_group __ARGS((char_u *name));
7534static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007535static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7536static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007537static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007538static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007539static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007540static int do_autocmd_event __ARGS((event_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007541static char_u *getnextac __ARGS((int c, void *cookie, int indent));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007542static 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 +00007543static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7544
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007545
Bram Moolenaar754b5602006-02-09 23:53:20 +00007546static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007547static int last_group;
Bram Moolenaar78ab3312007-09-29 12:16:41 +00007548static int autocmd_blocked = 0; /* block all autocmds */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007549
7550/*
7551 * Show the autocommands for one AutoPat.
7552 */
7553 static void
7554show_autocmd(ap, event)
7555 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007556 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007557{
7558 AutoCmd *ac;
7559
7560 /* Check for "got_int" (here and at various places below), which is set
7561 * when "q" has been hit for the "--more--" prompt */
7562 if (got_int)
7563 return;
7564 if (ap->pat == NULL) /* pattern has been removed */
7565 return;
7566
7567 msg_putchar('\n');
7568 if (got_int)
7569 return;
7570 if (event != last_event || ap->group != last_group)
7571 {
7572 if (ap->group != AUGROUP_DEFAULT)
7573 {
7574 if (AUGROUP_NAME(ap->group) == NULL)
7575 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7576 else
7577 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7578 msg_puts((char_u *)" ");
7579 }
7580 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7581 last_event = event;
7582 last_group = ap->group;
7583 msg_putchar('\n');
7584 if (got_int)
7585 return;
7586 }
7587 msg_col = 4;
7588 msg_outtrans(ap->pat);
7589
7590 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7591 {
7592 if (ac->cmd != NULL) /* skip removed commands */
7593 {
7594 if (msg_col >= 14)
7595 msg_putchar('\n');
7596 msg_col = 14;
7597 if (got_int)
7598 return;
7599 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007600#ifdef FEAT_EVAL
7601 if (p_verbose > 0)
7602 last_set_msg(ac->scriptID);
7603#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007604 if (got_int)
7605 return;
7606 if (ac->next != NULL)
7607 {
7608 msg_putchar('\n');
7609 if (got_int)
7610 return;
7611 }
7612 }
7613 }
7614}
7615
7616/*
7617 * Mark an autocommand pattern for deletion.
7618 */
7619 static void
7620au_remove_pat(ap)
7621 AutoPat *ap;
7622{
7623 vim_free(ap->pat);
7624 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007625 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007626 au_need_clean = TRUE;
7627}
7628
7629/*
7630 * Mark all commands for a pattern for deletion.
7631 */
7632 static void
7633au_remove_cmds(ap)
7634 AutoPat *ap;
7635{
7636 AutoCmd *ac;
7637
7638 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7639 {
7640 vim_free(ac->cmd);
7641 ac->cmd = NULL;
7642 }
7643 au_need_clean = TRUE;
7644}
7645
7646/*
7647 * Cleanup autocommands and patterns that have been deleted.
7648 * This is only done when not executing autocommands.
7649 */
7650 static void
7651au_cleanup()
7652{
7653 AutoPat *ap, **prev_ap;
7654 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007655 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007656
7657 if (autocmd_busy || !au_need_clean)
7658 return;
7659
7660 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007661 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7662 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007663 {
7664 /* loop over all autocommand patterns */
7665 prev_ap = &(first_autopat[(int)event]);
7666 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7667 {
7668 /* loop over all commands for this pattern */
7669 prev_ac = &(ap->cmds);
7670 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7671 {
7672 /* remove the command if the pattern is to be deleted or when
7673 * the command has been marked for deletion */
7674 if (ap->pat == NULL || ac->cmd == NULL)
7675 {
7676 *prev_ac = ac->next;
7677 vim_free(ac->cmd);
7678 vim_free(ac);
7679 }
7680 else
7681 prev_ac = &(ac->next);
7682 }
7683
7684 /* remove the pattern if it has been marked for deletion */
7685 if (ap->pat == NULL)
7686 {
7687 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007688 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007689 vim_free(ap);
7690 }
7691 else
7692 prev_ap = &(ap->next);
7693 }
7694 }
7695
7696 au_need_clean = FALSE;
7697}
7698
7699/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007700 * Called when buffer is freed, to remove/invalidate related buffer-local
7701 * autocmds.
7702 */
7703 void
7704aubuflocal_remove(buf)
7705 buf_T *buf;
7706{
7707 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007708 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007709 AutoPatCmd *apc;
7710
7711 /* invalidate currently executing autocommands */
7712 for (apc = active_apc_list; apc; apc = apc->next)
7713 if (buf->b_fnum == apc->arg_bufnr)
7714 apc->arg_bufnr = 0;
7715
7716 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007717 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7718 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007719 /* loop over all autocommand patterns */
7720 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7721 if (ap->buflocal_nr == buf->b_fnum)
7722 {
7723 au_remove_pat(ap);
7724 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007725 {
7726 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007727 smsg((char_u *)
7728 _("auto-removing autocommand: %s <buffer=%d>"),
7729 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007730 verbose_leave();
7731 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007732 }
7733 au_cleanup();
7734}
7735
7736/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007737 * Add an autocmd group name.
7738 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7739 */
7740 static int
7741au_new_group(name)
7742 char_u *name;
7743{
7744 int i;
7745
7746 i = au_find_group(name);
7747 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
7748 {
7749 /* First try using a free entry. */
7750 for (i = 0; i < augroups.ga_len; ++i)
7751 if (AUGROUP_NAME(i) == NULL)
7752 break;
7753 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
7754 return AUGROUP_ERROR;
7755
7756 AUGROUP_NAME(i) = vim_strsave(name);
7757 if (AUGROUP_NAME(i) == NULL)
7758 return AUGROUP_ERROR;
7759 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007760 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007761 }
7762
7763 return i;
7764}
7765
7766 static void
7767au_del_group(name)
7768 char_u *name;
7769{
7770 int i;
7771
7772 i = au_find_group(name);
7773 if (i == AUGROUP_ERROR) /* the group doesn't exist */
7774 EMSG2(_("E367: No such group: \"%s\""), name);
7775 else
7776 {
7777 vim_free(AUGROUP_NAME(i));
7778 AUGROUP_NAME(i) = NULL;
7779 }
7780}
7781
7782/*
7783 * Find the ID of an autocmd group name.
7784 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7785 */
7786 static int
7787au_find_group(name)
7788 char_u *name;
7789{
7790 int i;
7791
7792 for (i = 0; i < augroups.ga_len; ++i)
7793 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
7794 return i;
7795 return AUGROUP_ERROR;
7796}
7797
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007798/*
7799 * Return TRUE if augroup "name" exists.
7800 */
7801 int
7802au_has_group(name)
7803 char_u *name;
7804{
7805 return au_find_group(name) != AUGROUP_ERROR;
7806}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007807
Bram Moolenaar071d4272004-06-13 20:20:40 +00007808/*
7809 * ":augroup {name}".
7810 */
7811 void
7812do_augroup(arg, del_group)
7813 char_u *arg;
7814 int del_group;
7815{
7816 int i;
7817
7818 if (del_group)
7819 {
7820 if (*arg == NUL)
7821 EMSG(_(e_argreq));
7822 else
7823 au_del_group(arg);
7824 }
7825 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
7826 current_augroup = AUGROUP_DEFAULT;
7827 else if (*arg) /* ":aug xxx": switch to group xxx */
7828 {
7829 i = au_new_group(arg);
7830 if (i != AUGROUP_ERROR)
7831 current_augroup = i;
7832 }
7833 else /* ":aug": list the group names */
7834 {
7835 msg_start();
7836 for (i = 0; i < augroups.ga_len; ++i)
7837 {
7838 if (AUGROUP_NAME(i) != NULL)
7839 {
7840 msg_puts(AUGROUP_NAME(i));
7841 msg_puts((char_u *)" ");
7842 }
7843 }
7844 msg_clr_eos();
7845 msg_end();
7846 }
7847}
7848
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007849#if defined(EXITFREE) || defined(PROTO)
7850 void
7851free_all_autocmds()
7852{
7853 for (current_augroup = -1; current_augroup < augroups.ga_len;
7854 ++current_augroup)
7855 do_autocmd((char_u *)"", TRUE);
7856 ga_clear_strings(&augroups);
7857}
7858#endif
7859
Bram Moolenaar071d4272004-06-13 20:20:40 +00007860/*
7861 * Return the event number for event name "start".
7862 * Return NUM_EVENTS if the event name was not found.
7863 * Return a pointer to the next event name in "end".
7864 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007865 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00007866event_name2nr(start, end)
7867 char_u *start;
7868 char_u **end;
7869{
7870 char_u *p;
7871 int i;
7872 int len;
7873
7874 /* the event name ends with end of line, a blank or a comma */
7875 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7876 ;
7877 for (i = 0; event_names[i].name != NULL; ++i)
7878 {
7879 len = (int)STRLEN(event_names[i].name);
7880 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7881 break;
7882 }
7883 if (*p == ',')
7884 ++p;
7885 *end = p;
7886 if (event_names[i].name == NULL)
7887 return NUM_EVENTS;
7888 return event_names[i].event;
7889}
7890
7891/*
7892 * Return the name for event "event".
7893 */
7894 static char_u *
7895event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007896 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007897{
7898 int i;
7899
7900 for (i = 0; event_names[i].name != NULL; ++i)
7901 if (event_names[i].event == event)
7902 return (char_u *)event_names[i].name;
7903 return (char_u *)"Unknown";
7904}
7905
7906/*
7907 * Scan over the events. "*" stands for all events.
7908 */
7909 static char_u *
7910find_end_event(arg, have_group)
7911 char_u *arg;
7912 int have_group; /* TRUE when group name was found */
7913{
7914 char_u *pat;
7915 char_u *p;
7916
7917 if (*arg == '*')
7918 {
7919 if (arg[1] && !vim_iswhite(arg[1]))
7920 {
7921 EMSG2(_("E215: Illegal character after *: %s"), arg);
7922 return NULL;
7923 }
7924 pat = arg + 1;
7925 }
7926 else
7927 {
7928 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7929 {
7930 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7931 {
7932 if (have_group)
7933 EMSG2(_("E216: No such event: %s"), pat);
7934 else
7935 EMSG2(_("E216: No such group or event: %s"), pat);
7936 return NULL;
7937 }
7938 }
7939 }
7940 return pat;
7941}
7942
7943/*
7944 * Return TRUE if "event" is included in 'eventignore'.
7945 */
7946 static int
7947event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007948 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007949{
7950 char_u *p = p_ei;
7951
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007952 while (*p != NUL)
7953 {
7954 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
7955 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007956 if (event_name2nr(p, &p) == event)
7957 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007958 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007959
7960 return FALSE;
7961}
7962
7963/*
7964 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7965 */
7966 int
7967check_ei()
7968{
7969 char_u *p = p_ei;
7970
Bram Moolenaar071d4272004-06-13 20:20:40 +00007971 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007972 {
7973 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
7974 {
7975 p += 3;
7976 if (*p == ',')
7977 ++p;
7978 }
7979 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007980 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007981 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007982
7983 return OK;
7984}
7985
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007986# if defined(FEAT_SYN_HL) || defined(PROTO)
7987
7988/*
7989 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7990 * buffer loaded into the window. "what" must start with a comma.
7991 * Returns the old value of 'eventignore' in allocated memory.
7992 */
7993 char_u *
7994au_event_disable(what)
7995 char *what;
7996{
7997 char_u *new_ei;
7998 char_u *save_ei;
7999
8000 save_ei = vim_strsave(p_ei);
8001 if (save_ei != NULL)
8002 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00008003 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008004 if (new_ei != NULL)
8005 {
Bram Moolenaar8cac9fd2010-03-02 12:48:05 +01008006 if (*what == ',' && *p_ei == NUL)
8007 STRCPY(new_ei, what + 1);
8008 else
8009 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008010 set_string_option_direct((char_u *)"ei", -1, new_ei,
8011 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008012 vim_free(new_ei);
8013 }
8014 }
8015 return save_ei;
8016}
8017
8018 void
8019au_event_restore(old_ei)
8020 char_u *old_ei;
8021{
8022 if (old_ei != NULL)
8023 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00008024 set_string_option_direct((char_u *)"ei", -1, old_ei,
8025 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00008026 vim_free(old_ei);
8027 }
8028}
8029# endif /* FEAT_SYN_HL */
8030
Bram Moolenaar071d4272004-06-13 20:20:40 +00008031/*
8032 * do_autocmd() -- implements the :autocmd command. Can be used in the
8033 * following ways:
8034 *
8035 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
8036 * will be automatically executed for <event>
8037 * when editing a file matching <pat>, in
8038 * the current group.
8039 * :autocmd <event> <pat> Show the auto-commands associated with
8040 * <event> and <pat>.
8041 * :autocmd <event> Show the auto-commands associated with
8042 * <event>.
8043 * :autocmd Show all auto-commands.
8044 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
8045 * <event> and <pat>, and add the command
8046 * <cmd>, for the current group.
8047 * :autocmd! <event> <pat> Remove all auto-commands associated with
8048 * <event> and <pat> for the current group.
8049 * :autocmd! <event> Remove all auto-commands associated with
8050 * <event> for the current group.
8051 * :autocmd! Remove ALL auto-commands for the current
8052 * group.
8053 *
8054 * Multiple events and patterns may be given separated by commas. Here are
8055 * some examples:
8056 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
8057 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
8058 *
8059 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00008060 *
8061 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008062 */
8063 void
8064do_autocmd(arg, forceit)
8065 char_u *arg;
8066 int forceit;
8067{
8068 char_u *pat;
8069 char_u *envpat = NULL;
8070 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008071 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008072 int need_free = FALSE;
8073 int nested = FALSE;
8074 int group;
8075
8076 /*
8077 * Check for a legal group name. If not, use AUGROUP_ALL.
8078 */
8079 group = au_get_grouparg(&arg);
8080 if (arg == NULL) /* out of memory */
8081 return;
8082
8083 /*
8084 * Scan over the events.
8085 * If we find an illegal name, return here, don't do anything.
8086 */
8087 pat = find_end_event(arg, group != AUGROUP_ALL);
8088 if (pat == NULL)
8089 return;
8090
8091 /*
8092 * Scan over the pattern. Put a NUL at the end.
8093 */
8094 pat = skipwhite(pat);
8095 cmd = pat;
8096 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
8097 cmd++;
8098 if (*cmd)
8099 *cmd++ = NUL;
8100
8101 /* Expand environment variables in the pattern. Set 'shellslash', we want
8102 * forward slashes here. */
8103 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
8104 {
8105#ifdef BACKSLASH_IN_FILENAME
8106 int p_ssl_save = p_ssl;
8107
8108 p_ssl = TRUE;
8109#endif
8110 envpat = expand_env_save(pat);
8111#ifdef BACKSLASH_IN_FILENAME
8112 p_ssl = p_ssl_save;
8113#endif
8114 if (envpat != NULL)
8115 pat = envpat;
8116 }
8117
8118 /*
8119 * Check for "nested" flag.
8120 */
8121 cmd = skipwhite(cmd);
8122 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
8123 {
8124 nested = TRUE;
8125 cmd = skipwhite(cmd + 6);
8126 }
8127
8128 /*
8129 * Find the start of the commands.
8130 * Expand <sfile> in it.
8131 */
8132 if (*cmd != NUL)
8133 {
8134 cmd = expand_sfile(cmd);
8135 if (cmd == NULL) /* some error */
8136 return;
8137 need_free = TRUE;
8138 }
8139
8140 /*
8141 * Print header when showing autocommands.
8142 */
8143 if (!forceit && *cmd == NUL)
8144 {
8145 /* Highlight title */
8146 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
8147 }
8148
8149 /*
8150 * Loop over the events.
8151 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00008152 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008153 last_group = AUGROUP_ERROR; /* for listing the group name */
8154 if (*arg == '*' || *arg == NUL)
8155 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00008156 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
8157 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008158 if (do_autocmd_event(event, pat,
8159 nested, cmd, forceit, group) == FAIL)
8160 break;
8161 }
8162 else
8163 {
8164 while (*arg && !vim_iswhite(*arg))
8165 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
8166 nested, cmd, forceit, group) == FAIL)
8167 break;
8168 }
8169
8170 if (need_free)
8171 vim_free(cmd);
8172 vim_free(envpat);
8173}
8174
8175/*
8176 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
8177 * The "argp" argument is advanced to the following argument.
8178 *
8179 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
8180 */
8181 static int
8182au_get_grouparg(argp)
8183 char_u **argp;
8184{
8185 char_u *group_name;
8186 char_u *p;
8187 char_u *arg = *argp;
8188 int group = AUGROUP_ALL;
8189
8190 p = skiptowhite(arg);
8191 if (p > arg)
8192 {
8193 group_name = vim_strnsave(arg, (int)(p - arg));
8194 if (group_name == NULL) /* out of memory */
8195 return AUGROUP_ERROR;
8196 group = au_find_group(group_name);
8197 if (group == AUGROUP_ERROR)
8198 group = AUGROUP_ALL; /* no match, use all groups */
8199 else
8200 *argp = skipwhite(p); /* match, skip over group name */
8201 vim_free(group_name);
8202 }
8203 return group;
8204}
8205
8206/*
8207 * do_autocmd() for one event.
8208 * If *pat == NUL do for all patterns.
8209 * If *cmd == NUL show entries.
8210 * If forceit == TRUE delete entries.
8211 * If group is not AUGROUP_ALL, only use this group.
8212 */
8213 static int
8214do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008215 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008216 char_u *pat;
8217 int nested;
8218 char_u *cmd;
8219 int forceit;
8220 int group;
8221{
8222 AutoPat *ap;
8223 AutoPat **prev_ap;
8224 AutoCmd *ac;
8225 AutoCmd **prev_ac;
8226 int brace_level;
8227 char_u *endpat;
8228 int findgroup;
8229 int allgroups;
8230 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008231 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008232 int buflocal_nr;
8233 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008234
8235 if (group == AUGROUP_ALL)
8236 findgroup = current_augroup;
8237 else
8238 findgroup = group;
8239 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
8240
8241 /*
8242 * Show or delete all patterns for an event.
8243 */
8244 if (*pat == NUL)
8245 {
8246 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8247 {
8248 if (forceit) /* delete the AutoPat, if it's in the current group */
8249 {
8250 if (ap->group == findgroup)
8251 au_remove_pat(ap);
8252 }
8253 else if (group == AUGROUP_ALL || ap->group == group)
8254 show_autocmd(ap, event);
8255 }
8256 }
8257
8258 /*
8259 * Loop through all the specified patterns.
8260 */
8261 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
8262 {
8263 /*
8264 * Find end of the pattern.
8265 * Watch out for a comma in braces, like "*.\{obj,o\}".
8266 */
8267 brace_level = 0;
8268 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
8269 || endpat[-1] == '\\'); ++endpat)
8270 {
8271 if (*endpat == '{')
8272 brace_level++;
8273 else if (*endpat == '}')
8274 brace_level--;
8275 }
8276 if (pat == endpat) /* ignore single comma */
8277 continue;
8278 patlen = (int)(endpat - pat);
8279
8280 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008281 * detect special <buflocal[=X]> buffer-local patterns
8282 */
8283 is_buflocal = FALSE;
8284 buflocal_nr = 0;
8285
8286 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
8287 && pat[patlen - 1] == '>')
8288 {
8289 /* Error will be printed only for addition. printing and removing
8290 * will proceed silently. */
8291 is_buflocal = TRUE;
8292 if (patlen == 8)
8293 buflocal_nr = curbuf->b_fnum;
8294 else if (patlen > 9 && pat[7] == '=')
8295 {
8296 /* <buffer=abuf> */
8297 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
8298 buflocal_nr = autocmd_bufnr;
8299 /* <buffer=123> */
8300 else if (skipdigits(pat + 8) == pat + patlen - 1)
8301 buflocal_nr = atoi((char *)pat + 8);
8302 }
8303 }
8304
8305 if (is_buflocal)
8306 {
8307 /* normalize pat into standard "<buffer>#N" form */
8308 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
8309 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008310 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008311 }
8312
8313 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008314 * Find AutoPat entries with this pattern.
8315 */
8316 prev_ap = &first_autopat[(int)event];
8317 while ((ap = *prev_ap) != NULL)
8318 {
8319 if (ap->pat != NULL)
8320 {
8321 /* Accept a pattern when:
8322 * - a group was specified and it's that group, or a group was
8323 * not specified and it's the current group, or a group was
8324 * not specified and we are listing
8325 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008326 * - the pattern matches.
8327 * For <buffer[=X]>, this condition works because we normalize
8328 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008329 */
8330 if ((allgroups || ap->group == findgroup)
8331 && ap->patlen == patlen
8332 && STRNCMP(pat, ap->pat, patlen) == 0)
8333 {
8334 /*
8335 * Remove existing autocommands.
8336 * If adding any new autocmd's for this AutoPat, don't
8337 * delete the pattern from the autopat list, append to
8338 * this list.
8339 */
8340 if (forceit)
8341 {
8342 if (*cmd != NUL && ap->next == NULL)
8343 {
8344 au_remove_cmds(ap);
8345 break;
8346 }
8347 au_remove_pat(ap);
8348 }
8349
8350 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008351 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00008352 */
8353 else if (*cmd == NUL)
8354 show_autocmd(ap, event);
8355
8356 /*
8357 * Add autocmd to this autopat, if it's the last one.
8358 */
8359 else if (ap->next == NULL)
8360 break;
8361 }
8362 }
8363 prev_ap = &ap->next;
8364 }
8365
8366 /*
8367 * Add a new command.
8368 */
8369 if (*cmd != NUL)
8370 {
8371 /*
8372 * If the pattern we want to add a command to does appear at the
8373 * end of the list (or not is not in the list at all), add the
8374 * pattern at the end of the list.
8375 */
8376 if (ap == NULL)
8377 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008378 /* refuse to add buffer-local ap if buffer number is invalid */
8379 if (is_buflocal && (buflocal_nr == 0
8380 || buflist_findnr(buflocal_nr) == NULL))
8381 {
8382 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
8383 buflocal_nr);
8384 return FAIL;
8385 }
8386
Bram Moolenaar071d4272004-06-13 20:20:40 +00008387 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
8388 if (ap == NULL)
8389 return FAIL;
8390 ap->pat = vim_strnsave(pat, patlen);
8391 ap->patlen = patlen;
8392 if (ap->pat == NULL)
8393 {
8394 vim_free(ap);
8395 return FAIL;
8396 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008397
8398 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008399 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008400 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008401 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008402 }
8403 else
8404 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008405 char_u *reg_pat;
8406
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008407 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008408 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008409 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008410 if (reg_pat != NULL)
8411 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008412 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008413 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008414 {
8415 vim_free(ap->pat);
8416 vim_free(ap);
8417 return FAIL;
8418 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008419 }
8420 ap->cmds = NULL;
8421 *prev_ap = ap;
8422 ap->next = NULL;
8423 if (group == AUGROUP_ALL)
8424 ap->group = current_augroup;
8425 else
8426 ap->group = group;
8427 }
8428
8429 /*
8430 * Add the autocmd at the end of the AutoCmd list.
8431 */
8432 prev_ac = &(ap->cmds);
8433 while ((ac = *prev_ac) != NULL)
8434 prev_ac = &ac->next;
8435 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8436 if (ac == NULL)
8437 return FAIL;
8438 ac->cmd = vim_strsave(cmd);
8439#ifdef FEAT_EVAL
8440 ac->scriptID = current_SID;
8441#endif
8442 if (ac->cmd == NULL)
8443 {
8444 vim_free(ac);
8445 return FAIL;
8446 }
8447 ac->next = NULL;
8448 *prev_ac = ac;
8449 ac->nested = nested;
8450 }
8451 }
8452
8453 au_cleanup(); /* may really delete removed patterns/commands now */
8454 return OK;
8455}
8456
8457/*
8458 * Implementation of ":doautocmd [group] event [fname]".
8459 * Return OK for success, FAIL for failure;
8460 */
8461 int
8462do_doautocmd(arg, do_msg)
8463 char_u *arg;
8464 int do_msg; /* give message for no matching autocmds? */
8465{
8466 char_u *fname;
8467 int nothing_done = TRUE;
8468 int group;
8469
8470 /*
8471 * Check for a legal group name. If not, use AUGROUP_ALL.
8472 */
8473 group = au_get_grouparg(&arg);
8474 if (arg == NULL) /* out of memory */
8475 return FAIL;
8476
8477 if (*arg == '*')
8478 {
8479 EMSG(_("E217: Can't execute autocommands for ALL events"));
8480 return FAIL;
8481 }
8482
8483 /*
8484 * Scan over the events.
8485 * If we find an illegal name, return here, don't do anything.
8486 */
8487 fname = find_end_event(arg, group != AUGROUP_ALL);
8488 if (fname == NULL)
8489 return FAIL;
8490
8491 fname = skipwhite(fname);
8492
8493 /*
8494 * Loop over the events.
8495 */
8496 while (*arg && !vim_iswhite(*arg))
8497 if (apply_autocmds_group(event_name2nr(arg, &arg),
8498 fname, NULL, TRUE, group, curbuf, NULL))
8499 nothing_done = FALSE;
8500
8501 if (nothing_done && do_msg)
8502 MSG(_("No matching autocommands"));
8503
8504#ifdef FEAT_EVAL
8505 return aborting() ? FAIL : OK;
8506#else
8507 return OK;
8508#endif
8509}
8510
8511/*
8512 * ":doautoall": execute autocommands for each loaded buffer.
8513 */
8514 void
8515ex_doautoall(eap)
8516 exarg_T *eap;
8517{
8518 int retval;
8519 aco_save_T aco;
8520 buf_T *buf;
8521
8522 /*
8523 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8524 * equal to curbuf, but for some buffers there may not be a window.
8525 * So we change the buffer for the current window for a moment. This
8526 * gives problems when the autocommands make changes to the list of
8527 * buffers or windows...
8528 */
8529 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8530 {
Bram Moolenaar3a847972008-07-08 09:36:58 +00008531 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008532 {
8533 /* find a window for this buffer and save some values */
8534 aucmd_prepbuf(&aco, buf);
8535
8536 /* execute the autocommands for this buffer */
8537 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008538
8539 /* Execute the modeline settings, but don't set window-local
8540 * options if we are using the current window for another buffer. */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008541 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008542
8543 /* restore the current window */
8544 aucmd_restbuf(&aco);
8545
8546 /* stop if there is some error or buffer was deleted */
8547 if (retval == FAIL || !buf_valid(buf))
8548 break;
8549 }
8550 }
8551
8552 check_cursor(); /* just in case lines got deleted */
8553}
8554
8555/*
8556 * Prepare for executing autocommands for (hidden) buffer "buf".
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008557 * Search for a visible window containing the current buffer. If there isn't
8558 * one then use "aucmd_win".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008559 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008560 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008561 */
8562 void
8563aucmd_prepbuf(aco, buf)
8564 aco_save_T *aco; /* structure to save values in */
8565 buf_T *buf; /* new curbuf */
8566{
8567 win_T *win;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008568#ifdef FEAT_WINDOWS
8569 int save_ea;
8570#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008571
8572 /* Find a window that is for the new buffer */
8573 if (buf == curbuf) /* be quick when buf is curbuf */
8574 win = curwin;
8575 else
8576#ifdef FEAT_WINDOWS
8577 for (win = firstwin; win != NULL; win = win->w_next)
8578 if (win->w_buffer == buf)
8579 break;
8580#else
8581 win = NULL;
8582#endif
8583
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008584 /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
8585 * back to using the current window. */
8586 if (win == NULL && aucmd_win == NULL)
8587 {
8588 win_alloc_aucmd_win();
8589 if (aucmd_win == NULL)
8590 win = curwin;
8591 }
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008592 if (win == NULL && aucmd_win_used)
8593 /* Strange recursive autocommand, fall back to using the current
8594 * window. Expect a few side effects... */
8595 win = curwin;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008596
8597 aco->save_curwin = curwin;
8598 aco->save_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008599 if (win != NULL)
8600 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008601 /* There is a window for "buf" in the current tab page, make it the
8602 * curwin. This is preferred, it has the least side effects (esp. if
8603 * "buf" is curbuf). */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008604 aco->use_aucmd_win = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008605 curwin = win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008606 }
8607 else
8608 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008609 /* There is no window for "buf", use "aucmd_win". To minimize the side
8610 * effects, insert it in a the current tab page.
8611 * Anything related to a window (e.g., setting folds) may have
8612 * unexpected results. */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008613 aco->use_aucmd_win = TRUE;
8614 aucmd_win_used = TRUE;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008615 aucmd_win->w_buffer = buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008616 ++buf->b_nwindows;
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008617 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008618 vim_free(aucmd_win->w_localdir);
8619 aucmd_win->w_localdir = NULL;
8620
8621 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
8622 * win_enter_ext(). */
8623 aucmd_win->w_localdir = NULL;
8624 aco->globaldir = globaldir;
8625 globaldir = NULL;
8626
Bram Moolenaar071d4272004-06-13 20:20:40 +00008627
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008628#ifdef FEAT_WINDOWS
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008629 /* Split the current window, put the aucmd_win in the upper half.
8630 * We don't want the BufEnter or WinEnter autocommands. */
8631 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008632 make_snapshot(SNAP_AUCMD_IDX);
8633 save_ea = p_ea;
8634 p_ea = FALSE;
8635 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
8636 (void)win_comp_pos(); /* recompute window positions */
8637 p_ea = save_ea;
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008638 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008639#endif
Bram Moolenaarf061e0b2009-06-24 15:32:01 +00008640 curwin = aucmd_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008641 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008642 curbuf = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008643 aco->new_curwin = curwin;
8644 aco->new_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008645}
8646
8647/*
8648 * Cleanup after executing autocommands for a (hidden) buffer.
8649 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008650 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008651 */
8652 void
8653aucmd_restbuf(aco)
8654 aco_save_T *aco; /* structure holding saved values */
8655{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008656#ifdef FEAT_WINDOWS
8657 int dummy;
8658#endif
8659
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008660 if (aco->use_aucmd_win)
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008661 {
8662 --curbuf->b_nwindows;
8663#ifdef FEAT_WINDOWS
8664 /* Find "aucmd_win", it can't be closed, but it may be in another tab
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008665 * page. Do not trigger autocommands here. */
8666 block_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008667 if (curwin != aucmd_win)
8668 {
8669 tabpage_T *tp;
8670 win_T *wp;
8671
8672 FOR_ALL_TAB_WINDOWS(tp, wp)
8673 {
8674 if (wp == aucmd_win)
8675 {
8676 if (tp != curtab)
8677 goto_tabpage_tp(tp);
8678 win_goto(aucmd_win);
8679 break;
8680 }
8681 }
8682 }
8683
8684 /* Remove the window and frame from the tree of frames. */
8685 (void)winframe_remove(curwin, &dummy, NULL);
8686 win_remove(curwin, NULL);
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008687 aucmd_win_used = FALSE;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008688 last_status(FALSE); /* may need to remove last status line */
8689 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
8690 (void)win_comp_pos(); /* recompute window positions */
Bram Moolenaar2bc76e62009-07-01 15:13:56 +00008691 unblock_autocmds();
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008692
8693 if (win_valid(aco->save_curwin))
8694 curwin = aco->save_curwin;
8695 else
8696 /* Hmm, original window disappeared. Just use the first one. */
8697 curwin = firstwin;
8698# ifdef FEAT_EVAL
8699 vars_clear(&aucmd_win->w_vars.dv_hashtab); /* free all w: variables */
Bram Moolenaar50daf402009-11-17 13:57:22 +00008700 hash_init(&aucmd_win->w_vars.dv_hashtab); /* re-use the hashtab */
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008701# endif
8702#else
8703 curwin = aco->save_curwin;
8704#endif
8705 curbuf = curwin->w_buffer;
8706
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008707 vim_free(globaldir);
8708 globaldir = aco->globaldir;
8709
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008710 /* the buffer contents may have changed */
8711 check_cursor();
8712 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
8713 {
8714 curwin->w_topline = curbuf->b_ml.ml_line_count;
8715#ifdef FEAT_DIFF
8716 curwin->w_topfill = 0;
8717#endif
8718 }
8719#if defined(FEAT_GUI)
8720 /* Hide the scrollbars from the aucmd_win and update. */
8721 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
8722 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
8723 gui_may_update_scrollbars();
8724#endif
8725 }
8726 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008727 {
8728 /* restore curwin */
8729#ifdef FEAT_WINDOWS
8730 if (win_valid(aco->save_curwin))
8731#endif
8732 {
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008733 /* Restore the buffer which was previously edited by curwin, if
Bram Moolenaar6bef63c2009-07-29 10:10:29 +00008734 * it was changed, we are still the same window and the buffer is
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008735 * valid. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008736 if (curwin == aco->new_curwin
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008737 && curbuf != aco->new_curbuf
8738 && buf_valid(aco->new_curbuf)
8739 && aco->new_curbuf->b_ml.ml_mfp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008740 {
8741 --curbuf->b_nwindows;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00008742 curbuf = aco->new_curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008743 curwin->w_buffer = curbuf;
8744 ++curbuf->b_nwindows;
8745 }
8746
8747 curwin = aco->save_curwin;
8748 curbuf = curwin->w_buffer;
8749 }
8750 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008751}
8752
8753static int autocmd_nested = FALSE;
8754
8755/*
8756 * Execute autocommands for "event" and file name "fname".
8757 * Return TRUE if some commands were executed.
8758 */
8759 int
8760apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008761 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008762 char_u *fname; /* NULL or empty means use actual file name */
8763 char_u *fname_io; /* fname to use for <afile> on cmdline */
8764 int force; /* when TRUE, ignore autocmd_busy */
8765 buf_T *buf; /* buffer for <abuf> */
8766{
8767 return apply_autocmds_group(event, fname, fname_io, force,
8768 AUGROUP_ALL, buf, NULL);
8769}
8770
8771/*
8772 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
8773 * setting v:filearg.
8774 */
8775 static int
8776apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008777 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008778 char_u *fname;
8779 char_u *fname_io;
8780 int force;
8781 buf_T *buf;
8782 exarg_T *eap;
8783{
8784 return apply_autocmds_group(event, fname, fname_io, force,
8785 AUGROUP_ALL, buf, eap);
8786}
8787
8788/*
8789 * Like apply_autocmds(), but handles the caller's retval. If the script
8790 * processing is being aborted or if retval is FAIL when inside a try
8791 * conditional, no autocommands are executed. If otherwise the autocommands
8792 * cause the script to be aborted, retval is set to FAIL.
8793 */
8794 int
8795apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008796 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008797 char_u *fname; /* NULL or empty means use actual file name */
8798 char_u *fname_io; /* fname to use for <afile> on cmdline */
8799 int force; /* when TRUE, ignore autocmd_busy */
8800 buf_T *buf; /* buffer for <abuf> */
8801 int *retval; /* pointer to caller's retval */
8802{
8803 int did_cmd;
8804
Bram Moolenaar1e015462005-09-25 22:16:38 +00008805#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008806 if (should_abort(*retval))
8807 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00008808#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008809
8810 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
8811 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008812 if (did_cmd
8813#ifdef FEAT_EVAL
8814 && aborting()
8815#endif
8816 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008817 *retval = FAIL;
8818 return did_cmd;
8819}
8820
Bram Moolenaard35f9712005-12-18 22:02:33 +00008821/*
8822 * Return TRUE when there is a CursorHold autocommand defined.
8823 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008824 int
8825has_cursorhold()
8826{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008827 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
8828 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008829}
Bram Moolenaard35f9712005-12-18 22:02:33 +00008830
8831/*
8832 * Return TRUE if the CursorHold event can be triggered.
8833 */
8834 int
8835trigger_cursorhold()
8836{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008837 int state;
8838
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00008839 if (!did_cursorhold && has_cursorhold() && !Recording
8840#ifdef FEAT_INS_EXPAND
8841 && !ins_compl_active()
8842#endif
8843 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00008844 {
8845 state = get_real_state();
8846 if (state == NORMAL_BUSY || (state & INSERT) != 0)
8847 return TRUE;
8848 }
8849 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00008850}
Bram Moolenaar754b5602006-02-09 23:53:20 +00008851
8852/*
8853 * Return TRUE when there is a CursorMoved autocommand defined.
8854 */
8855 int
8856has_cursormoved()
8857{
8858 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
8859}
8860
8861/*
8862 * Return TRUE when there is a CursorMovedI autocommand defined.
8863 */
8864 int
8865has_cursormovedI()
8866{
8867 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
8868}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008869
8870 static int
8871apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008872 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008873 char_u *fname; /* NULL or empty means use actual file name */
8874 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
8875 use fname */
8876 int force; /* when TRUE, ignore autocmd_busy */
8877 int group; /* group ID, or AUGROUP_ALL */
8878 buf_T *buf; /* buffer for <abuf> */
8879 exarg_T *eap; /* command arguments */
8880{
8881 char_u *sfname = NULL; /* short file name */
8882 char_u *tail;
8883 int save_changed;
8884 buf_T *old_curbuf;
8885 int retval = FALSE;
8886 char_u *save_sourcing_name;
8887 linenr_T save_sourcing_lnum;
8888 char_u *save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00008889 int save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008890 int save_autocmd_bufnr;
8891 char_u *save_autocmd_match;
8892 int save_autocmd_busy;
8893 int save_autocmd_nested;
8894 static int nesting = 0;
8895 AutoPatCmd patcmd;
8896 AutoPat *ap;
8897#ifdef FEAT_EVAL
8898 scid_T save_current_SID;
8899 void *save_funccalp;
8900 char_u *save_cmdarg;
8901 long save_cmdbang;
8902#endif
8903 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00008904#ifdef FEAT_PROFILE
8905 proftime_T wait_time;
8906#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008907
8908 /*
8909 * Quickly return if there are no autocommands for this event or
8910 * autocommands are blocked.
8911 */
Bram Moolenaar78ab3312007-09-29 12:16:41 +00008912 if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008913 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008914
8915 /*
8916 * When autocommands are busy, new autocommands are only executed when
8917 * explicitly enabled with the "nested" flag.
8918 */
8919 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008920 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008921
8922#ifdef FEAT_EVAL
8923 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00008924 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00008925 * occurred or an exception was thrown but not caught.
8926 */
8927 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008928 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008929#endif
8930
8931 /*
8932 * FileChangedShell never nests, because it can create an endless loop.
8933 */
Bram Moolenaar56718732006-03-15 22:53:57 +00008934 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
8935 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008936 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008937
8938 /*
8939 * Ignore events in 'eventignore'.
8940 */
8941 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008942 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943
8944 /*
8945 * Allow nesting of autocommands, but restrict the depth, because it's
8946 * possible to create an endless loop.
8947 */
8948 if (nesting == 10)
8949 {
8950 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008951 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008952 }
8953
8954 /*
8955 * Check if these autocommands are disabled. Used when doing ":all" or
8956 * ":ball".
8957 */
8958 if ( (autocmd_no_enter
8959 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
8960 || (autocmd_no_leave
8961 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008962 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008963
8964 /*
8965 * Save the autocmd_* variables and info about the current buffer.
8966 */
8967 save_autocmd_fname = autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00008968 save_autocmd_fname_full = autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008969 save_autocmd_bufnr = autocmd_bufnr;
8970 save_autocmd_match = autocmd_match;
8971 save_autocmd_busy = autocmd_busy;
8972 save_autocmd_nested = autocmd_nested;
8973 save_changed = curbuf->b_changed;
8974 old_curbuf = curbuf;
8975
8976 /*
8977 * Set the file name to be used for <afile>.
Bram Moolenaara0174af2008-01-02 20:08:25 +00008978 * Make a copy to avoid that changing a buffer name or directory makes it
8979 * invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008980 */
8981 if (fname_io == NULL)
8982 {
8983 if (fname != NULL && *fname != NUL)
8984 autocmd_fname = fname;
8985 else if (buf != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00008986 autocmd_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008987 else
8988 autocmd_fname = NULL;
8989 }
8990 else
8991 autocmd_fname = fname_io;
Bram Moolenaara0174af2008-01-02 20:08:25 +00008992 if (autocmd_fname != NULL)
Bram Moolenaarf6dad432008-09-18 19:29:58 +00008993 autocmd_fname = vim_strsave(autocmd_fname);
8994 autocmd_fname_full = FALSE; /* call FullName_save() later */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008995
8996 /*
8997 * Set the buffer number to be used for <abuf>.
8998 */
8999 if (buf == NULL)
9000 autocmd_bufnr = 0;
9001 else
9002 autocmd_bufnr = buf->b_fnum;
9003
9004 /*
9005 * When the file name is NULL or empty, use the file name of buffer "buf".
9006 * Always use the full path of the file name to match with, in case
9007 * "allow_dirs" is set.
9008 */
9009 if (fname == NULL || *fname == NUL)
9010 {
9011 if (buf == NULL)
9012 fname = NULL;
9013 else
9014 {
9015#ifdef FEAT_SYN_HL
9016 if (event == EVENT_SYNTAX)
9017 fname = buf->b_p_syn;
9018 else
9019#endif
9020 if (event == EVENT_FILETYPE)
9021 fname = buf->b_p_ft;
9022 else
9023 {
9024 if (buf->b_sfname != NULL)
9025 sfname = vim_strsave(buf->b_sfname);
9026 fname = buf->b_ffname;
9027 }
9028 }
9029 if (fname == NULL)
9030 fname = (char_u *)"";
9031 fname = vim_strsave(fname); /* make a copy, so we can change it */
9032 }
9033 else
9034 {
9035 sfname = vim_strsave(fname);
Bram Moolenaar5135d462009-04-29 16:03:38 +00009036 /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID or
9037 * QuickFixCmd* */
Bram Moolenaar7c626922005-02-07 22:01:03 +00009038 if (event == EVENT_FILETYPE
9039 || event == EVENT_SYNTAX
Bram Moolenaar5135d462009-04-29 16:03:38 +00009040 || event == EVENT_FUNCUNDEFINED
Bram Moolenaar7c626922005-02-07 22:01:03 +00009041 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00009042 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00009043 || event == EVENT_QUICKFIXCMDPRE
9044 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009045 fname = vim_strsave(fname);
9046 else
9047 fname = FullName_save(fname, FALSE);
9048 }
9049 if (fname == NULL) /* out of memory */
9050 {
9051 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009052 retval = FALSE;
9053 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009054 }
9055
9056#ifdef BACKSLASH_IN_FILENAME
9057 /*
9058 * Replace all backslashes with forward slashes. This makes the
9059 * autocommand patterns portable between Unix and MS-DOS.
9060 */
9061 if (sfname != NULL)
9062 forward_slash(sfname);
9063 forward_slash(fname);
9064#endif
9065
9066#ifdef VMS
9067 /* remove version for correct match */
9068 if (sfname != NULL)
9069 vms_remove_version(sfname);
9070 vms_remove_version(fname);
9071#endif
9072
9073 /*
9074 * Set the name to be used for <amatch>.
9075 */
9076 autocmd_match = fname;
9077
9078
9079 /* Don't redraw while doing auto commands. */
9080 ++RedrawingDisabled;
9081 save_sourcing_name = sourcing_name;
9082 sourcing_name = NULL; /* don't free this one */
9083 save_sourcing_lnum = sourcing_lnum;
9084 sourcing_lnum = 0; /* no line number here */
9085
9086#ifdef FEAT_EVAL
9087 save_current_SID = current_SID;
9088
Bram Moolenaar05159a02005-02-26 23:04:13 +00009089# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009090 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009091 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
9092# endif
9093
Bram Moolenaar071d4272004-06-13 20:20:40 +00009094 /* Don't use local function variables, if called from a function */
9095 save_funccalp = save_funccal();
9096#endif
9097
9098 /*
9099 * When starting to execute autocommands, save the search patterns.
9100 */
9101 if (!autocmd_busy)
9102 {
9103 save_search_patterns();
9104 saveRedobuff();
9105 did_filetype = keep_filetype;
9106 }
9107
9108 /*
9109 * Note that we are applying autocmds. Some commands need to know.
9110 */
9111 autocmd_busy = TRUE;
9112 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
9113 ++nesting; /* see matching decrement below */
9114
9115 /* Remember that FileType was triggered. Used for did_filetype(). */
9116 if (event == EVENT_FILETYPE)
9117 did_filetype = TRUE;
9118
9119 tail = gettail(fname);
9120
9121 /* Find first autocommand that matches */
9122 patcmd.curpat = first_autopat[(int)event];
9123 patcmd.nextcmd = NULL;
9124 patcmd.group = group;
9125 patcmd.fname = fname;
9126 patcmd.sfname = sfname;
9127 patcmd.tail = tail;
9128 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009129 patcmd.arg_bufnr = autocmd_bufnr;
9130 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009131 auto_next_pat(&patcmd, FALSE);
9132
9133 /* found one, start executing the autocommands */
9134 if (patcmd.curpat != NULL)
9135 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009136 /* add to active_apc_list */
9137 patcmd.next = active_apc_list;
9138 active_apc_list = &patcmd;
9139
Bram Moolenaar071d4272004-06-13 20:20:40 +00009140#ifdef FEAT_EVAL
9141 /* set v:cmdarg (only when there is a matching pattern) */
9142 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
9143 if (eap != NULL)
9144 {
9145 save_cmdarg = set_cmdarg(eap, NULL);
9146 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
9147 }
9148 else
9149 save_cmdarg = NULL; /* avoid gcc warning */
9150#endif
9151 retval = TRUE;
9152 /* mark the last pattern, to avoid an endless loop when more patterns
9153 * are added when executing autocommands */
9154 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
9155 ap->last = FALSE;
9156 ap->last = TRUE;
9157 check_lnums(TRUE); /* make sure cursor and topline are valid */
9158 do_cmdline(NULL, getnextac, (void *)&patcmd,
9159 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9160#ifdef FEAT_EVAL
9161 if (eap != NULL)
9162 {
9163 (void)set_cmdarg(NULL, save_cmdarg);
9164 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
9165 }
9166#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009167 /* delete from active_apc_list */
9168 if (active_apc_list == &patcmd) /* just in case */
9169 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009170 }
9171
9172 --RedrawingDisabled;
9173 autocmd_busy = save_autocmd_busy;
9174 filechangeshell_busy = FALSE;
9175 autocmd_nested = save_autocmd_nested;
9176 vim_free(sourcing_name);
9177 sourcing_name = save_sourcing_name;
9178 sourcing_lnum = save_sourcing_lnum;
Bram Moolenaara0174af2008-01-02 20:08:25 +00009179 vim_free(autocmd_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009180 autocmd_fname = save_autocmd_fname;
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009181 autocmd_fname_full = save_autocmd_fname_full;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009182 autocmd_bufnr = save_autocmd_bufnr;
9183 autocmd_match = save_autocmd_match;
9184#ifdef FEAT_EVAL
9185 current_SID = save_current_SID;
9186 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00009187# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00009188 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00009189 prof_child_exit(&wait_time);
9190# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009191#endif
9192 vim_free(fname);
9193 vim_free(sfname);
9194 --nesting; /* see matching increment above */
9195
9196 /*
9197 * When stopping to execute autocommands, restore the search patterns and
9198 * the redo buffer.
9199 */
9200 if (!autocmd_busy)
9201 {
9202 restore_search_patterns();
9203 restoreRedobuff();
9204 did_filetype = FALSE;
9205 }
9206
9207 /*
9208 * Some events don't set or reset the Changed flag.
9209 * Check if still in the same buffer!
9210 */
9211 if (curbuf == old_curbuf
9212 && (event == EVENT_BUFREADPOST
9213 || event == EVENT_BUFWRITEPOST
9214 || event == EVENT_FILEAPPENDPOST
9215 || event == EVENT_VIMLEAVE
9216 || event == EVENT_VIMLEAVEPRE))
9217 {
9218#ifdef FEAT_TITLE
9219 if (curbuf->b_changed != save_changed)
9220 need_maketitle = TRUE;
9221#endif
9222 curbuf->b_changed = save_changed;
9223 }
9224
9225 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009226
9227BYPASS_AU:
9228 /* When wiping out a buffer make sure all its buffer-local autocommands
9229 * are deleted. */
9230 if (event == EVENT_BUFWIPEOUT && buf != NULL)
9231 aubuflocal_remove(buf);
9232
Bram Moolenaar071d4272004-06-13 20:20:40 +00009233 return retval;
9234}
9235
Bram Moolenaar78ab3312007-09-29 12:16:41 +00009236# ifdef FEAT_EVAL
9237static char_u *old_termresponse = NULL;
9238# endif
9239
9240/*
9241 * Block triggering autocommands until unblock_autocmd() is called.
9242 * Can be used recursively, so long as it's symmetric.
9243 */
9244 void
9245block_autocmds()
9246{
9247# ifdef FEAT_EVAL
9248 /* Remember the value of v:termresponse. */
9249 if (autocmd_blocked == 0)
9250 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
9251# endif
9252 ++autocmd_blocked;
9253}
9254
9255 void
9256unblock_autocmds()
9257{
9258 --autocmd_blocked;
9259
9260# ifdef FEAT_EVAL
9261 /* When v:termresponse was set while autocommands were blocked, trigger
9262 * the autocommands now. Esp. useful when executing a shell command
9263 * during startup (vimdiff). */
9264 if (autocmd_blocked == 0
9265 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
9266 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
9267# endif
9268}
9269
Bram Moolenaar071d4272004-06-13 20:20:40 +00009270/*
9271 * Find next autocommand pattern that matches.
9272 */
9273 static void
9274auto_next_pat(apc, stop_at_last)
9275 AutoPatCmd *apc;
9276 int stop_at_last; /* stop when 'last' flag is set */
9277{
9278 AutoPat *ap;
9279 AutoCmd *cp;
9280 char_u *name;
9281 char *s;
9282
9283 vim_free(sourcing_name);
9284 sourcing_name = NULL;
9285
9286 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
9287 {
9288 apc->curpat = NULL;
9289
Bram Moolenaarf6dad432008-09-18 19:29:58 +00009290 /* Only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009291 * the group matches. For buffer-local autocommands only check the
9292 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009293 if (ap->pat != NULL && ap->cmds != NULL
9294 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
9295 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009296 /* execution-condition */
9297 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009298 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
9299 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009300 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009301 {
9302 name = event_nr2name(apc->event);
9303 s = _("%s Auto commands for \"%s\"");
9304 sourcing_name = alloc((unsigned)(STRLEN(s)
9305 + STRLEN(name) + ap->patlen + 1));
9306 if (sourcing_name != NULL)
9307 {
9308 sprintf((char *)sourcing_name, s,
9309 (char *)name, (char *)ap->pat);
9310 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009311 {
9312 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009313 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009314 verbose_leave();
9315 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009316 }
9317
9318 apc->curpat = ap;
9319 apc->nextcmd = ap->cmds;
9320 /* mark last command */
9321 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
9322 cp->last = FALSE;
9323 cp->last = TRUE;
9324 }
9325 line_breakcheck();
9326 if (apc->curpat != NULL) /* found a match */
9327 break;
9328 }
9329 if (stop_at_last && ap->last)
9330 break;
9331 }
9332}
9333
9334/*
9335 * Get next autocommand command.
9336 * Called by do_cmdline() to get the next line for ":if".
9337 * Returns allocated string, or NULL for end of autocommands.
9338 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009339 static char_u *
9340getnextac(c, cookie, indent)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009341 int c UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009342 void *cookie;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009343 int indent UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009344{
9345 AutoPatCmd *acp = (AutoPatCmd *)cookie;
9346 char_u *retval;
9347 AutoCmd *ac;
9348
9349 /* Can be called again after returning the last line. */
9350 if (acp->curpat == NULL)
9351 return NULL;
9352
9353 /* repeat until we find an autocommand to execute */
9354 for (;;)
9355 {
9356 /* skip removed commands */
9357 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
9358 if (acp->nextcmd->last)
9359 acp->nextcmd = NULL;
9360 else
9361 acp->nextcmd = acp->nextcmd->next;
9362
9363 if (acp->nextcmd != NULL)
9364 break;
9365
9366 /* at end of commands, find next pattern that matches */
9367 if (acp->curpat->last)
9368 acp->curpat = NULL;
9369 else
9370 acp->curpat = acp->curpat->next;
9371 if (acp->curpat != NULL)
9372 auto_next_pat(acp, TRUE);
9373 if (acp->curpat == NULL)
9374 return NULL;
9375 }
9376
9377 ac = acp->nextcmd;
9378
9379 if (p_verbose >= 9)
9380 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009381 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00009382 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009383 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00009384 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009385 }
9386 retval = vim_strsave(ac->cmd);
9387 autocmd_nested = ac->nested;
9388#ifdef FEAT_EVAL
9389 current_SID = ac->scriptID;
9390#endif
9391 if (ac->last)
9392 acp->nextcmd = NULL;
9393 else
9394 acp->nextcmd = ac->next;
9395 return retval;
9396}
9397
9398/*
9399 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009400 * To account for buffer-local autocommands, function needs to know
9401 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009402 */
9403 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009404has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00009405 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009406 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009407 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009408{
9409 AutoPat *ap;
9410 char_u *fname;
9411 char_u *tail = gettail(sfname);
9412 int retval = FALSE;
9413
9414 fname = FullName_save(sfname, FALSE);
9415 if (fname == NULL)
9416 return FALSE;
9417
9418#ifdef BACKSLASH_IN_FILENAME
9419 /*
9420 * Replace all backslashes with forward slashes. This makes the
9421 * autocommand patterns portable between Unix and MS-DOS.
9422 */
9423 sfname = vim_strsave(sfname);
9424 if (sfname != NULL)
9425 forward_slash(sfname);
9426 forward_slash(fname);
9427#endif
9428
9429 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
9430 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009431 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00009432 ? match_file_pat(NULL, ap->reg_prog,
9433 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00009434 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009435 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009436 {
9437 retval = TRUE;
9438 break;
9439 }
9440
9441 vim_free(fname);
9442#ifdef BACKSLASH_IN_FILENAME
9443 vim_free(sfname);
9444#endif
9445
9446 return retval;
9447}
9448
9449#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9450/*
9451 * Function given to ExpandGeneric() to obtain the list of autocommand group
9452 * names.
9453 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009454 char_u *
9455get_augroup_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009456 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009457 int idx;
9458{
9459 if (idx == augroups.ga_len) /* add "END" add the end */
9460 return (char_u *)"END";
9461 if (idx >= augroups.ga_len) /* end of list */
9462 return NULL;
9463 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
9464 return (char_u *)"";
9465 return AUGROUP_NAME(idx); /* return a name */
9466}
9467
9468static int include_groups = FALSE;
9469
9470 char_u *
9471set_context_in_autocmd(xp, arg, doautocmd)
9472 expand_T *xp;
9473 char_u *arg;
Bram Moolenaard812df62008-11-09 12:46:09 +00009474 int doautocmd; /* TRUE for :doauto*, FALSE for :autocmd */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009475{
9476 char_u *p;
9477 int group;
9478
9479 /* check for a group name, skip it if present */
9480 include_groups = FALSE;
9481 p = arg;
9482 group = au_get_grouparg(&arg);
9483 if (group == AUGROUP_ERROR)
9484 return NULL;
9485 /* If there only is a group name that's what we expand. */
9486 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
9487 {
9488 arg = p;
9489 group = AUGROUP_ALL;
9490 }
9491
9492 /* skip over event name */
9493 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
9494 if (*p == ',')
9495 arg = p + 1;
9496 if (*p == NUL)
9497 {
9498 if (group == AUGROUP_ALL)
9499 include_groups = TRUE;
9500 xp->xp_context = EXPAND_EVENTS; /* expand event name */
9501 xp->xp_pattern = arg;
9502 return NULL;
9503 }
9504
9505 /* skip over pattern */
9506 arg = skipwhite(p);
9507 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
9508 arg++;
9509 if (*arg)
9510 return arg; /* expand (next) command */
9511
9512 if (doautocmd)
9513 xp->xp_context = EXPAND_FILES; /* expand file names */
9514 else
9515 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9516 return NULL;
9517}
9518
9519/*
9520 * Function given to ExpandGeneric() to obtain the list of event names.
9521 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009522 char_u *
9523get_event_name(xp, idx)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009524 expand_T *xp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009525 int idx;
9526{
9527 if (idx < augroups.ga_len) /* First list group names, if wanted */
9528 {
9529 if (!include_groups || AUGROUP_NAME(idx) == NULL)
9530 return (char_u *)""; /* skip deleted entries */
9531 return AUGROUP_NAME(idx); /* return a name */
9532 }
9533 return (char_u *)event_names[idx - augroups.ga_len].name;
9534}
9535
9536#endif /* FEAT_CMDL_COMPL */
9537
9538/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009539 * Return TRUE if autocmd is supported.
9540 */
9541 int
9542autocmd_supported(name)
9543 char_u *name;
9544{
9545 char_u *p;
9546
9547 return (event_name2nr(name, &p) != NUM_EVENTS);
9548}
9549
9550/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00009551 * Return TRUE if an autocommand is defined for a group, event and
9552 * pattern: The group can be omitted to accept any group. "event" and "pattern"
9553 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
9554 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
9555 * Used for:
9556 * exists("#Group") or
9557 * exists("#Group#Event") or
9558 * exists("#Group#Event#pat") or
9559 * exists("#Event") or
9560 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00009561 */
9562 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00009563au_exists(arg)
9564 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009565{
Bram Moolenaar195d6352005-12-19 22:08:24 +00009566 char_u *arg_save;
9567 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009568 char_u *event_name;
9569 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00009570 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009571 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009572 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00009573 int group;
9574 int retval = FALSE;
9575
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009576 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009577 arg_save = vim_strsave(arg);
9578 if (arg_save == NULL)
9579 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009580 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00009581 if (p != NULL)
9582 *p++ = NUL;
9583
9584 /* First, look for an autocmd group name */
9585 group = au_find_group(arg_save);
9586 if (group == AUGROUP_ERROR)
9587 {
9588 /* Didn't match a group name, assume the first argument is an event. */
9589 group = AUGROUP_ALL;
9590 event_name = arg_save;
9591 }
9592 else
9593 {
9594 if (p == NULL)
9595 {
9596 /* "Group": group name is present and it's recognized */
9597 retval = TRUE;
9598 goto theend;
9599 }
9600
9601 /* Must be "Group#Event" or "Group#Event#pat". */
9602 event_name = p;
9603 p = vim_strchr(event_name, '#');
9604 if (p != NULL)
9605 *p++ = NUL; /* "Group#Event#pat" */
9606 }
9607
9608 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009609
9610 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009611 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009612
9613 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009614 if (event == NUM_EVENTS)
9615 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009616
9617 /* Find the first autocommand for this event.
9618 * If there isn't any, return FALSE;
9619 * If there is one and no pattern given, return TRUE; */
9620 ap = first_autopat[(int)event];
9621 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009622 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009623
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009624 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9625 /* for pattern "<buffer=N>, fnamecmp() will work fine */
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009626 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009627 buflocal_buf = curbuf;
9628
Bram Moolenaar071d4272004-06-13 20:20:40 +00009629 /* Check if there is an autocommand with the given pattern. */
9630 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009631 /* only use a pattern when it has not been removed and has commands. */
9632 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009633 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00009634 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaar5b7880d2009-09-11 15:24:31 +00009635 && (pattern == NULL
9636 || (buflocal_buf == NULL
9637 ? fnamecmp(ap->pat, pattern) == 0
9638 : ap->buflocal_nr == buflocal_buf->b_fnum)))
Bram Moolenaar195d6352005-12-19 22:08:24 +00009639 {
9640 retval = TRUE;
9641 break;
9642 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009643
Bram Moolenaar195d6352005-12-19 22:08:24 +00009644theend:
9645 vim_free(arg_save);
9646 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009647}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009648
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009649#else /* FEAT_AUTOCMD */
9650
9651/*
9652 * Prepare for executing commands for (hidden) buffer "buf".
9653 * This is the non-autocommand version, it simply saves "curbuf" and sets
9654 * "curbuf" and "curwin" to match "buf".
9655 */
9656 void
9657aucmd_prepbuf(aco, buf)
9658 aco_save_T *aco; /* structure to save values in */
9659 buf_T *buf; /* new curbuf */
9660{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009661 aco->save_curbuf = curbuf;
9662 --curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009663 curbuf = buf;
9664 curwin->w_buffer = buf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009665 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009666}
9667
9668/*
9669 * Restore after executing commands for a (hidden) buffer.
9670 * This is the non-autocommand version.
9671 */
9672 void
9673aucmd_restbuf(aco)
9674 aco_save_T *aco; /* structure holding saved values */
9675{
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009676 --curbuf->b_nwindows;
9677 curbuf = aco->save_curbuf;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009678 curwin->w_buffer = curbuf;
Bram Moolenaar746ebd32009-06-16 14:01:43 +00009679 ++curbuf->b_nwindows;
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009680}
9681
Bram Moolenaar071d4272004-06-13 20:20:40 +00009682#endif /* FEAT_AUTOCMD */
9683
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009684
Bram Moolenaar071d4272004-06-13 20:20:40 +00009685#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
9686/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00009687 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
9688 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
9689 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009690 * Used for autocommands and 'wildignore'.
9691 * Returns TRUE if there is a match, FALSE otherwise.
9692 */
9693 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00009694match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009695 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00009696 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009697 char_u *fname; /* full path of file name */
9698 char_u *sfname; /* short file name or NULL */
9699 char_u *tail; /* tail of path */
9700 int allow_dirs; /* allow matching with dir */
9701{
9702 regmatch_T regmatch;
9703 int result = FALSE;
9704#ifdef FEAT_OSFILETYPE
9705 int no_pattern = FALSE; /* TRUE if check is filetype only */
9706 char_u *type_start;
9707 char_u c;
9708 int match = FALSE;
9709#endif
9710
9711#ifdef CASE_INSENSITIVE_FILENAME
9712 regmatch.rm_ic = TRUE; /* Always ignore case */
9713#else
9714 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
9715#endif
9716#ifdef FEAT_OSFILETYPE
9717 if (*pattern == '<')
9718 {
9719 /* There is a filetype condition specified with this pattern.
9720 * Check the filetype matches first. If not, don't bother with the
9721 * pattern (set regprog to NULL).
9722 * Always use magic for the regexp.
9723 */
9724
9725 for (type_start = pattern + 1; (c = *pattern); pattern++)
9726 {
9727 if ((c == ';' || c == '>') && match == FALSE)
9728 {
9729 *pattern = NUL; /* Terminate the string */
9730 match = mch_check_filetype(fname, type_start);
9731 *pattern = c; /* Restore the terminator */
9732 type_start = pattern + 1;
9733 }
9734 if (c == '>')
9735 break;
9736 }
9737
9738 /* (c should never be NUL, but check anyway) */
9739 if (match == FALSE || c == NUL)
9740 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
9741 else if (*pattern == NUL)
9742 {
9743 regmatch.regprog = NULL; /* Vim will try to free regprog later */
9744 no_pattern = TRUE; /* Always matches - don't check pat. */
9745 }
9746 else
9747 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
9748 }
9749 else
9750#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00009751 {
9752 if (prog != NULL)
9753 regmatch.regprog = prog;
9754 else
9755 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
9756 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009757
9758 /*
9759 * Try for a match with the pattern with:
9760 * 1. the full file name, when the pattern has a '/'.
9761 * 2. the short file name, when the pattern has a '/'.
9762 * 3. the tail of the file name, when the pattern has no '/'.
9763 */
9764 if (
9765#ifdef FEAT_OSFILETYPE
9766 /* If the check is for a filetype only and we don't care
9767 * about the path then skip all the regexp stuff.
9768 */
9769 no_pattern ||
9770#endif
9771 (regmatch.regprog != NULL
9772 && ((allow_dirs
9773 && (vim_regexec(&regmatch, fname, (colnr_T)0)
9774 || (sfname != NULL
9775 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
9776 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
9777 result = TRUE;
9778
Bram Moolenaar748bf032005-02-02 23:04:36 +00009779 if (prog == NULL)
9780 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009781 return result;
9782}
9783#endif
9784
9785#if defined(FEAT_WILDIGN) || defined(PROTO)
9786/*
9787 * Return TRUE if a file matches with a pattern in "list".
9788 * "list" is a comma-separated list of patterns, like 'wildignore'.
9789 * "sfname" is the short file name or NULL, "ffname" the long file name.
9790 */
9791 int
9792match_file_list(list, sfname, ffname)
9793 char_u *list;
9794 char_u *sfname;
9795 char_u *ffname;
9796{
9797 char_u buf[100];
9798 char_u *tail;
9799 char_u *regpat;
9800 char allow_dirs;
9801 int match;
9802 char_u *p;
9803
9804 tail = gettail(sfname);
9805
9806 /* try all patterns in 'wildignore' */
9807 p = list;
9808 while (*p)
9809 {
9810 copy_option_part(&p, buf, 100, ",");
9811 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
9812 if (regpat == NULL)
9813 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00009814 match = match_file_pat(regpat, NULL, ffname, sfname,
9815 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009816 vim_free(regpat);
9817 if (match)
9818 return TRUE;
9819 }
9820 return FALSE;
9821}
9822#endif
9823
9824/*
9825 * Convert the given pattern "pat" which has shell style wildcards in it, into
9826 * a regular expression, and return the result in allocated memory. If there
9827 * is a directory path separator to be matched, then TRUE is put in
9828 * allow_dirs, otherwise FALSE is put there -- webb.
9829 * Handle backslashes before special characters, like "\*" and "\ ".
9830 *
9831 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
9832 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
9833 *
9834 * Returns NULL when out of memory.
9835 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009836 char_u *
9837file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
9838 char_u *pat;
9839 char_u *pat_end; /* first char after pattern or NULL */
9840 char *allow_dirs; /* Result passed back out in here */
Bram Moolenaar78a15312009-05-15 19:33:18 +00009841 int no_bslash UNUSED; /* Don't use a backward slash as pathsep */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009842{
9843 int size;
9844 char_u *endp;
9845 char_u *reg_pat;
9846 char_u *p;
9847 int i;
9848 int nested = 0;
9849 int add_dollar = TRUE;
9850#ifdef FEAT_OSFILETYPE
9851 int check_length = 0;
9852#endif
9853
9854 if (allow_dirs != NULL)
9855 *allow_dirs = FALSE;
9856 if (pat_end == NULL)
9857 pat_end = pat + STRLEN(pat);
9858
9859#ifdef FEAT_OSFILETYPE
9860 /* Find out how much of the string is the filetype check */
9861 if (*pat == '<')
9862 {
9863 /* Count chars until the next '>' */
9864 for (p = pat + 1; p < pat_end && *p != '>'; p++)
9865 ;
9866 if (p < pat_end)
9867 {
9868 /* Pattern is of the form <.*>.* */
9869 check_length = p - pat + 1;
9870 if (p + 1 >= pat_end)
9871 {
9872 /* The 'pattern' is a filetype check ONLY */
9873 reg_pat = (char_u *)alloc(check_length + 1);
9874 if (reg_pat != NULL)
9875 {
9876 mch_memmove(reg_pat, pat, (size_t)check_length);
9877 reg_pat[check_length] = NUL;
9878 }
9879 return reg_pat;
9880 }
9881 }
9882 /* else: there was no closing '>' - assume it was a normal pattern */
9883
9884 }
9885 pat += check_length;
9886 size = 2 + check_length;
9887#else
9888 size = 2; /* '^' at start, '$' at end */
9889#endif
9890
9891 for (p = pat; p < pat_end; p++)
9892 {
9893 switch (*p)
9894 {
9895 case '*':
9896 case '.':
9897 case ',':
9898 case '{':
9899 case '}':
9900 case '~':
9901 size += 2; /* extra backslash */
9902 break;
9903#ifdef BACKSLASH_IN_FILENAME
9904 case '\\':
9905 case '/':
9906 size += 4; /* could become "[\/]" */
9907 break;
9908#endif
9909 default:
9910 size++;
9911# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009912 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009913 {
9914 ++p;
9915 ++size;
9916 }
9917# endif
9918 break;
9919 }
9920 }
9921 reg_pat = alloc(size + 1);
9922 if (reg_pat == NULL)
9923 return NULL;
9924
9925#ifdef FEAT_OSFILETYPE
9926 /* Copy the type check in to the start. */
9927 if (check_length)
9928 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
9929 i = check_length;
9930#else
9931 i = 0;
9932#endif
9933
9934 if (pat[0] == '*')
9935 while (pat[0] == '*' && pat < pat_end - 1)
9936 pat++;
9937 else
9938 reg_pat[i++] = '^';
9939 endp = pat_end - 1;
9940 if (*endp == '*')
9941 {
9942 while (endp - pat > 0 && *endp == '*')
9943 endp--;
9944 add_dollar = FALSE;
9945 }
9946 for (p = pat; *p && nested >= 0 && p <= endp; p++)
9947 {
9948 switch (*p)
9949 {
9950 case '*':
9951 reg_pat[i++] = '.';
9952 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +00009953 while (p[1] == '*') /* "**" matches like "*" */
9954 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009955 break;
9956 case '.':
9957#ifdef RISCOS
9958 if (allow_dirs != NULL)
9959 *allow_dirs = TRUE;
9960 /* FALLTHROUGH */
9961#endif
9962 case '~':
9963 reg_pat[i++] = '\\';
9964 reg_pat[i++] = *p;
9965 break;
9966 case '?':
9967#ifdef RISCOS
9968 case '#':
9969#endif
9970 reg_pat[i++] = '.';
9971 break;
9972 case '\\':
9973 if (p[1] == NUL)
9974 break;
9975#ifdef BACKSLASH_IN_FILENAME
9976 if (!no_bslash)
9977 {
9978 /* translate:
9979 * "\x" to "\\x" e.g., "dir\file"
9980 * "\*" to "\\.*" e.g., "dir\*.c"
9981 * "\?" to "\\." e.g., "dir\??.c"
9982 * "\+" to "\+" e.g., "fileX\+.c"
9983 */
9984 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
9985 && p[1] != '+')
9986 {
9987 reg_pat[i++] = '[';
9988 reg_pat[i++] = '\\';
9989 reg_pat[i++] = '/';
9990 reg_pat[i++] = ']';
9991 if (allow_dirs != NULL)
9992 *allow_dirs = TRUE;
9993 break;
9994 }
9995 }
9996#endif
9997 if (*++p == '?'
9998#ifdef BACKSLASH_IN_FILENAME
9999 && no_bslash
10000#endif
10001 )
10002 reg_pat[i++] = '?';
10003 else
10004 if (*p == ',')
10005 reg_pat[i++] = ',';
10006 else
10007 {
10008 if (allow_dirs != NULL && vim_ispathsep(*p)
10009#ifdef BACKSLASH_IN_FILENAME
10010 && (!no_bslash || *p != '\\')
10011#endif
10012 )
10013 *allow_dirs = TRUE;
10014 reg_pat[i++] = '\\';
10015 reg_pat[i++] = *p;
10016 }
10017 break;
10018#ifdef BACKSLASH_IN_FILENAME
10019 case '/':
10020 reg_pat[i++] = '[';
10021 reg_pat[i++] = '\\';
10022 reg_pat[i++] = '/';
10023 reg_pat[i++] = ']';
10024 if (allow_dirs != NULL)
10025 *allow_dirs = TRUE;
10026 break;
10027#endif
10028 case '{':
10029 reg_pat[i++] = '\\';
10030 reg_pat[i++] = '(';
10031 nested++;
10032 break;
10033 case '}':
10034 reg_pat[i++] = '\\';
10035 reg_pat[i++] = ')';
10036 --nested;
10037 break;
10038 case ',':
10039 if (nested)
10040 {
10041 reg_pat[i++] = '\\';
10042 reg_pat[i++] = '|';
10043 }
10044 else
10045 reg_pat[i++] = ',';
10046 break;
10047 default:
10048# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010049 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010050 reg_pat[i++] = *p++;
10051 else
10052# endif
10053 if (allow_dirs != NULL && vim_ispathsep(*p))
10054 *allow_dirs = TRUE;
10055 reg_pat[i++] = *p;
10056 break;
10057 }
10058 }
10059 if (add_dollar)
10060 reg_pat[i++] = '$';
10061 reg_pat[i] = NUL;
10062 if (nested != 0)
10063 {
10064 if (nested < 0)
10065 EMSG(_("E219: Missing {."));
10066 else
10067 EMSG(_("E220: Missing }."));
10068 vim_free(reg_pat);
10069 reg_pat = NULL;
10070 }
10071 return reg_pat;
10072}