blob: 3f094d4ef1ea022808aad340823c6b44b379bfe1 [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
24#ifdef HAVE_FCNTL_H
25# include <fcntl.h>
26#endif
27
28#ifdef __TANDEM
29# include <limits.h> /* for SSIZE_MAX */
30#endif
31
32#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
33# include <utime.h> /* for struct utimbuf */
34#endif
35
36#define BUFSIZE 8192 /* size of normal write buffer */
37#define SMBUFSIZE 256 /* size of emergency write buffer */
38
39#ifdef FEAT_CRYPT
40# define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */
41# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
42#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
61static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));
62#endif
63#ifdef UNIX
64static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
65#endif
Bram Moolenaar2d3f4892006-01-20 23:02:51 +000066static int set_rw_fname __ARGS((char_u *fname, char_u *sfname));
Bram Moolenaar071d4272004-06-13 20:20:40 +000067static int msg_add_fileformat __ARGS((int eol_type));
Bram Moolenaar071d4272004-06-13 20:20:40 +000068static void msg_add_eol __ARGS((void));
69static int check_mtime __ARGS((buf_T *buf, struct stat *s));
70static int time_differs __ARGS((long t1, long t2));
71#ifdef FEAT_AUTOCMD
Bram Moolenaar754b5602006-02-09 23:53:20 +000072static 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 +000073static int au_find_group __ARGS((char_u *name));
74
75# define AUGROUP_DEFAULT -1 /* default autocmd group */
76# define AUGROUP_ERROR -2 /* errornouse autocmd group */
77# define AUGROUP_ALL -3 /* all autocmd groups */
Bram Moolenaar071d4272004-06-13 20:20:40 +000078#endif
79
80#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
81# define HAS_BW_FLAGS
82# define FIO_LATIN1 0x01 /* convert Latin1 */
83# define FIO_UTF8 0x02 /* convert UTF-8 */
84# define FIO_UCS2 0x04 /* convert UCS-2 */
85# define FIO_UCS4 0x08 /* convert UCS-4 */
86# define FIO_UTF16 0x10 /* convert UTF-16 */
87# ifdef WIN3264
88# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
89# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
90# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
91# endif
92# ifdef MACOS_X
93# define FIO_MACROMAN 0x20 /* convert MacRoman */
94# endif
95# define FIO_ENDIAN_L 0x80 /* little endian */
96# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
97# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
98# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
99# define FIO_ALL -1 /* allow all formats */
100#endif
101
102/* When converting, a read() or write() may leave some bytes to be converted
103 * for the next call. The value is guessed... */
104#define CONV_RESTLEN 30
105
106/* We have to guess how much a sequence of bytes may expand when converting
107 * with iconv() to be able to allocate a buffer. */
108#define ICONV_MULT 8
109
110/*
111 * Structure to pass arguments from buf_write() to buf_write_bytes().
112 */
113struct bw_info
114{
115 int bw_fd; /* file descriptor */
116 char_u *bw_buf; /* buffer with data to be written */
117 int bw_len; /* lenght of data */
118#ifdef HAS_BW_FLAGS
119 int bw_flags; /* FIO_ flags */
120#endif
121#ifdef FEAT_MBYTE
122 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
123 int bw_restlen; /* nr of bytes in bw_rest[] */
124 int bw_first; /* first write call */
125 char_u *bw_conv_buf; /* buffer for writing converted chars */
126 int bw_conv_buflen; /* size of bw_conv_buf */
127 int bw_conv_error; /* set for conversion error */
128# ifdef USE_ICONV
129 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
130# endif
131#endif
132};
133
134static int buf_write_bytes __ARGS((struct bw_info *ip));
135
136#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000137static linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
139static int same_encoding __ARGS((char_u *a, char_u *b));
140static int get_fio_flags __ARGS((char_u *ptr));
141static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
142static int make_bom __ARGS((char_u *buf, char_u *name));
143# ifdef WIN3264
144static int get_win_fio_flags __ARGS((char_u *ptr));
145# endif
146# ifdef MACOS_X
147static int get_mac_fio_flags __ARGS((char_u *ptr));
148# endif
149#endif
150static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
151
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000152
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153 void
154filemess(buf, name, s, attr)
155 buf_T *buf;
156 char_u *name;
157 char_u *s;
158 int attr;
159{
160 int msg_scroll_save;
161
162 if (msg_silent != 0)
163 return;
164 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
165 /* If it's extremely long, truncate it. */
166 if (STRLEN(IObuff) > IOSIZE - 80)
167 IObuff[IOSIZE - 80] = NUL;
168 STRCAT(IObuff, s);
169 /*
170 * For the first message may have to start a new line.
171 * For further ones overwrite the previous one, reset msg_scroll before
172 * calling filemess().
173 */
174 msg_scroll_save = msg_scroll;
175 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
176 msg_scroll = FALSE;
177 if (!msg_scroll) /* wait a bit when overwriting an error msg */
178 check_for_delay(FALSE);
179 msg_start();
180 msg_scroll = msg_scroll_save;
181 msg_scrolled_ign = TRUE;
182 /* may truncate the message to avoid a hit-return prompt */
183 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
184 msg_clr_eos();
185 out_flush();
186 msg_scrolled_ign = FALSE;
187}
188
189/*
190 * Read lines from file "fname" into the buffer after line "from".
191 *
192 * 1. We allocate blocks with lalloc, as big as possible.
193 * 2. Each block is filled with characters from the file with a single read().
194 * 3. The lines are inserted in the buffer with ml_append().
195 *
196 * (caller must check that fname != NULL, unless READ_STDIN is used)
197 *
198 * "lines_to_skip" is the number of lines that must be skipped
199 * "lines_to_read" is the number of lines that are appended
200 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
201 *
202 * flags:
203 * READ_NEW starting to edit a new buffer
204 * READ_FILTER reading filter output
205 * READ_STDIN read from stdin instead of a file
206 * READ_BUFFER read from curbuf instead of a file (converting after reading
207 * stdin)
208 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
209 *
210 * return FAIL for failure, OK otherwise
211 */
212 int
213readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
214 char_u *fname;
215 char_u *sfname;
216 linenr_T from;
217 linenr_T lines_to_skip;
218 linenr_T lines_to_read;
219 exarg_T *eap; /* can be NULL! */
220 int flags;
221{
222 int fd = 0;
223 int newfile = (flags & READ_NEW);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000224 int set_options = newfile || (eap != NULL && eap->read_edit);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225 int check_readonly;
226 int filtering = (flags & READ_FILTER);
227 int read_stdin = (flags & READ_STDIN);
228 int read_buffer = (flags & READ_BUFFER);
229 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
230 colnr_T read_buf_col = 0; /* next char to read from this line */
231 char_u c;
232 linenr_T lnum = from;
233 char_u *ptr = NULL; /* pointer into read buffer */
234 char_u *buffer = NULL; /* read buffer */
235 char_u *new_buffer = NULL; /* init to shut up gcc */
236 char_u *line_start = NULL; /* init to shut up gcc */
237 int wasempty; /* buffer was empty before reading */
238 colnr_T len;
239 long size = 0;
240 char_u *p;
241 long filesize = 0;
242 int skip_read = FALSE;
243#ifdef FEAT_CRYPT
244 char_u *cryptkey = NULL;
245#endif
246 int split = 0; /* number of split lines */
247#define UNKNOWN 0x0fffffff /* file size is unknown */
248 linenr_T linecnt;
249 int error = FALSE; /* errors encountered */
250 int ff_error = EOL_UNKNOWN; /* file format with errors */
251 long linerest = 0; /* remaining chars in line */
252#ifdef UNIX
253 int perm = 0;
254 int swap_mode = -1; /* protection bits for swap file */
255#else
256 int perm;
257#endif
258 int fileformat = 0; /* end-of-line format */
259 int keep_fileformat = FALSE;
260 struct stat st;
261 int file_readonly;
262 linenr_T skip_count = 0;
263 linenr_T read_count = 0;
264 int msg_save = msg_scroll;
265 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
266 * last read was missing the eol */
267 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
268 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
269 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
270 int file_rewind = FALSE;
271#ifdef FEAT_MBYTE
272 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000273 linenr_T conv_error = 0; /* line nr with conversion error */
274 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000275 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
276 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000277 int bad_char_behavior = BAD_REPLACE;
278 /* BAD_KEEP, BAD_DROP or character to
279 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000280 char_u *tmpname = NULL; /* name of 'charconvert' output file */
281 int fio_flags = 0;
282 char_u *fenc; /* fileencoding to use */
283 int fenc_alloced; /* fenc_next is in allocated memory */
284 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
285 int advance_fenc = FALSE;
286 long real_size = 0;
287# ifdef USE_ICONV
288 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
289# ifdef FEAT_EVAL
290 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
291 'charconvert' next */
292# endif
293# endif
294 int converted = FALSE; /* TRUE if conversion done */
295 int notconverted = FALSE; /* TRUE if conversion wanted but it
296 wasn't possible */
297 char_u conv_rest[CONV_RESTLEN];
298 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
299#endif
300
Bram Moolenaar071d4272004-06-13 20:20:40 +0000301 write_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000302
303 /*
304 * If there is no file name yet, use the one for the read file.
305 * BF_NOTEDITED is set to reflect this.
306 * Don't do this for a read from a filter.
307 * Only do this when 'cpoptions' contains the 'f' flag.
308 */
309 if (curbuf->b_ffname == NULL
310 && !filtering
311 && fname != NULL
312 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
313 && !(flags & READ_DUMMY))
314 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000315 if (set_rw_fname(fname, sfname) == FAIL)
316 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000317 }
318
Bram Moolenaardf177f62005-02-22 08:39:57 +0000319 /* After reading a file the cursor line changes but we don't want to
320 * display the line. */
321 ex_no_reprint = TRUE;
322
Bram Moolenaar55b7cf82006-09-09 12:52:42 +0000323 /* don't display the file info for another buffer now */
324 need_fileinfo = FALSE;
325
Bram Moolenaar071d4272004-06-13 20:20:40 +0000326 /*
327 * For Unix: Use the short file name whenever possible.
328 * Avoids problems with networks and when directory names are changed.
329 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
330 * another directory, which we don't detect.
331 */
332 if (sfname == NULL)
333 sfname = fname;
334#if defined(UNIX) || defined(__EMX__)
335 fname = sfname;
336#endif
337
338#ifdef FEAT_AUTOCMD
339 /*
340 * The BufReadCmd and FileReadCmd events intercept the reading process by
341 * executing the associated commands instead.
342 */
343 if (!filtering && !read_stdin && !read_buffer)
344 {
345 pos_T pos;
346
347 pos = curbuf->b_op_start;
348
349 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
350 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
351 curbuf->b_op_start.col = 0;
352
353 if (newfile)
354 {
355 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
356 FALSE, curbuf, eap))
357#ifdef FEAT_EVAL
358 return aborting() ? FAIL : OK;
359#else
360 return OK;
361#endif
362 }
363 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
364 FALSE, NULL, eap))
365#ifdef FEAT_EVAL
366 return aborting() ? FAIL : OK;
367#else
368 return OK;
369#endif
370
371 curbuf->b_op_start = pos;
372 }
373#endif
374
375 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
376 msg_scroll = FALSE; /* overwrite previous file message */
377 else
378 msg_scroll = TRUE; /* don't overwrite previous file message */
379
380 /*
381 * If the name ends in a path separator, we can't open it. Check here,
382 * because reading the file may actually work, but then creating the swap
383 * file may destroy it! Reported on MS-DOS and Win 95.
384 * If the name is too long we might crash further on, quit here.
385 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000386 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000387 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000388 p = fname + STRLEN(fname);
389 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000390 {
391 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
392 msg_end();
393 msg_scroll = msg_save;
394 return FAIL;
395 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000396 }
397
398#ifdef UNIX
399 /*
400 * On Unix it is possible to read a directory, so we have to
401 * check for it before the mch_open().
402 */
403 if (!read_stdin && !read_buffer)
404 {
405 perm = mch_getperm(fname);
406 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
407# ifdef S_ISFIFO
408 && !S_ISFIFO(perm) /* ... or fifo */
409# endif
410# ifdef S_ISSOCK
411 && !S_ISSOCK(perm) /* ... or socket */
412# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +0000413# ifdef OPEN_CHR_FILES
414 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
415 /* ... or a character special file named /dev/fd/<n> */
416# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 )
418 {
419 if (S_ISDIR(perm))
420 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
421 else
422 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
423 msg_end();
424 msg_scroll = msg_save;
425 return FAIL;
426 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000427
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000428# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
429 /*
430 * MS-Windows allows opening a device, but we will probably get stuck
431 * trying to read it.
432 */
433 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
434 {
Bram Moolenaar5386a122007-06-28 20:02:32 +0000435 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
Bram Moolenaarc67764a2006-10-12 19:14:26 +0000436 msg_end();
437 msg_scroll = msg_save;
438 return FAIL;
439 }
440# endif
Bram Moolenaar043545e2006-10-10 16:44:07 +0000441 }
442#endif
443
Bram Moolenaar071d4272004-06-13 20:20:40 +0000444 /* set default 'fileformat' */
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000445 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 {
447 if (eap != NULL && eap->force_ff != 0)
448 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
449 else if (*p_ffs != NUL)
450 set_fileformat(default_fileformat(), OPT_LOCAL);
451 }
452
453 /* set or reset 'binary' */
454 if (eap != NULL && eap->force_bin != 0)
455 {
456 int oldval = curbuf->b_p_bin;
457
458 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
459 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
460 }
461
462 /*
463 * When opening a new file we take the readonly flag from the file.
464 * Default is r/w, can be set to r/o below.
465 * Don't reset it when in readonly mode
466 * Only set/reset b_p_ro when BF_CHECK_RO is set.
467 */
468 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000469 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000470 curbuf->b_p_ro = FALSE;
471
472 if (newfile && !read_stdin && !read_buffer)
473 {
474 /* Remember time of file.
475 * For RISCOS, also remember the filetype.
476 */
477 if (mch_stat((char *)fname, &st) >= 0)
478 {
479 buf_store_time(curbuf, &st, fname);
480 curbuf->b_mtime_read = curbuf->b_mtime;
481
482#if defined(RISCOS) && defined(FEAT_OSFILETYPE)
483 /* Read the filetype into the buffer local filetype option. */
484 mch_read_filetype(fname);
485#endif
486#ifdef UNIX
487 /*
488 * Use the protection bits of the original file for the swap file.
489 * This makes it possible for others to read the name of the
490 * edited file from the swapfile, but only if they can read the
491 * edited file.
492 * Remove the "write" and "execute" bits for group and others
493 * (they must not write the swapfile).
494 * Add the "read" and "write" bits for the user, otherwise we may
495 * not be able to write to the file ourselves.
496 * Setting the bits is done below, after creating the swap file.
497 */
498 swap_mode = (st.st_mode & 0644) | 0600;
499#endif
500#ifdef FEAT_CW_EDITOR
501 /* Get the FSSpec on MacOS
502 * TODO: Update it properly when the buffer name changes
503 */
504 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
505#endif
506#ifdef VMS
507 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000508 curbuf->b_fab_rat = st.st_fab_rat;
509 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000510#endif
511 }
512 else
513 {
514 curbuf->b_mtime = 0;
515 curbuf->b_mtime_read = 0;
516 curbuf->b_orig_size = 0;
517 curbuf->b_orig_mode = 0;
518 }
519
520 /* Reset the "new file" flag. It will be set again below when the
521 * file doesn't exist. */
522 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
523 }
524
525/*
526 * for UNIX: check readonly with perm and mch_access()
527 * for RISCOS: same as Unix, otherwise file gets re-datestamped!
528 * for MSDOS and Amiga: check readonly by trying to open the file for writing
529 */
530 file_readonly = FALSE;
531 if (read_stdin)
532 {
533#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
534 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
535 setmode(0, O_BINARY);
536#endif
537 }
538 else if (!read_buffer)
539 {
540#ifdef USE_MCH_ACCESS
541 if (
542# ifdef UNIX
543 !(perm & 0222) ||
544# endif
545 mch_access((char *)fname, W_OK))
546 file_readonly = TRUE;
547 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
548#else
549 if (!newfile
550 || readonlymode
551 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
552 {
553 file_readonly = TRUE;
554 /* try to open ro */
555 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
556 }
557#endif
558 }
559
560 if (fd < 0) /* cannot open at all */
561 {
562#ifndef UNIX
563 int isdir_f;
564#endif
565 msg_scroll = msg_save;
566#ifndef UNIX
567 /*
568 * On MSDOS and Amiga we can't open a directory, check here.
569 */
570 isdir_f = (mch_isdir(fname));
571 perm = mch_getperm(fname); /* check if the file exists */
572 if (isdir_f)
573 {
574 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
575 curbuf->b_p_ro = TRUE; /* must use "w!" now */
576 }
577 else
578#endif
579 if (newfile)
580 {
581 if (perm < 0)
582 {
583 /*
584 * Set the 'new-file' flag, so that when the file has
585 * been created by someone else, a ":w" will complain.
586 */
587 curbuf->b_flags |= BF_NEW;
588
589 /* Create a swap file now, so that other Vims are warned
590 * that we are editing this file. Don't do this for a
591 * "nofile" or "nowrite" buffer type. */
592#ifdef FEAT_QUICKFIX
593 if (!bt_dontwrite(curbuf))
594#endif
595 check_need_swap(newfile);
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000596 if (dir_of_file_exists(fname))
597 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
598 else
599 filemess(curbuf, sfname,
600 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000601#ifdef FEAT_VIMINFO
602 /* Even though this is a new file, it might have been
603 * edited before and deleted. Get the old marks. */
604 check_marks_read();
605#endif
606#ifdef FEAT_MBYTE
607 if (eap != NULL && eap->force_enc != 0)
608 {
609 /* set forced 'fileencoding' */
610 fenc = enc_canonize(eap->cmd + eap->force_enc);
611 if (fenc != NULL)
612 set_string_option_direct((char_u *)"fenc", -1,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000613 fenc, OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000614 vim_free(fenc);
615 }
616#endif
617#ifdef FEAT_AUTOCMD
618 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
619 FALSE, curbuf, eap);
620#endif
621 /* remember the current fileformat */
622 save_file_ff(curbuf);
623
624#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
625 if (aborting()) /* autocmds may abort script processing */
626 return FAIL;
627#endif
628 return OK; /* a new file is not an error */
629 }
630 else
631 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000632 filemess(curbuf, sfname, (char_u *)(
633# ifdef EFBIG
634 (errno == EFBIG) ? _("[File too big]") :
635# endif
636 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637 curbuf->b_p_ro = TRUE; /* must use "w!" now */
638 }
639 }
640
641 return FAIL;
642 }
643
644 /*
645 * Only set the 'ro' flag for readonly files the first time they are
646 * loaded. Help files always get readonly mode
647 */
648 if ((check_readonly && file_readonly) || curbuf->b_help)
649 curbuf->b_p_ro = TRUE;
650
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000651 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000652 {
653 curbuf->b_p_eol = TRUE;
654 curbuf->b_start_eol = TRUE;
655#ifdef FEAT_MBYTE
656 curbuf->b_p_bomb = FALSE;
657#endif
658 }
659
660 /* Create a swap file now, so that other Vims are warned that we are
661 * editing this file.
662 * Don't do this for a "nofile" or "nowrite" buffer type. */
663#ifdef FEAT_QUICKFIX
664 if (!bt_dontwrite(curbuf))
665#endif
666 {
667 check_need_swap(newfile);
668#ifdef UNIX
669 /* Set swap file protection bits after creating it. */
670 if (swap_mode > 0 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
671 (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
672#endif
673 }
674
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000675#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676 /* If "Quit" selected at ATTENTION dialog, don't load the file */
677 if (swap_exists_action == SEA_QUIT)
678 {
679 if (!read_buffer && !read_stdin)
680 close(fd);
681 return FAIL;
682 }
683#endif
684
685 ++no_wait_return; /* don't wait for return yet */
686
687 /*
688 * Set '[ mark to the line above where the lines go (line 1 if zero).
689 */
690 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
691 curbuf->b_op_start.col = 0;
692
693#ifdef FEAT_AUTOCMD
694 if (!read_buffer)
695 {
696 int m = msg_scroll;
697 int n = msg_scrolled;
698 buf_T *old_curbuf = curbuf;
699
700 /*
701 * The file must be closed again, the autocommands may want to change
702 * the file before reading it.
703 */
704 if (!read_stdin)
705 close(fd); /* ignore errors */
706
707 /*
708 * The output from the autocommands should not overwrite anything and
709 * should not be overwritten: Set msg_scroll, restore its value if no
710 * output was done.
711 */
712 msg_scroll = TRUE;
713 if (filtering)
714 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
715 FALSE, curbuf, eap);
716 else if (read_stdin)
717 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
718 FALSE, curbuf, eap);
719 else if (newfile)
720 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
721 FALSE, curbuf, eap);
722 else
723 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
724 FALSE, NULL, eap);
725 if (msg_scrolled == n)
726 msg_scroll = m;
727
728#ifdef FEAT_EVAL
729 if (aborting()) /* autocmds may abort script processing */
730 {
731 --no_wait_return;
732 msg_scroll = msg_save;
733 curbuf->b_p_ro = TRUE; /* must use "w!" now */
734 return FAIL;
735 }
736#endif
737 /*
738 * Don't allow the autocommands to change the current buffer.
739 * Try to re-open the file.
740 */
741 if (!read_stdin && (curbuf != old_curbuf
742 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
743 {
744 --no_wait_return;
745 msg_scroll = msg_save;
746 if (fd < 0)
747 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
748 else
749 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
750 curbuf->b_p_ro = TRUE; /* must use "w!" now */
751 return FAIL;
752 }
753 }
754#endif /* FEAT_AUTOCMD */
755
756 /* Autocommands may add lines to the file, need to check if it is empty */
757 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
758
759 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
760 {
761 /*
762 * Show the user that we are busy reading the input. Sometimes this
763 * may take a while. When reading from stdin another program may
764 * still be running, don't move the cursor to the last line, unless
765 * always using the GUI.
766 */
767 if (read_stdin)
768 {
769#ifndef ALWAYS_USE_GUI
770 mch_msg(_("Vim: Reading from stdin...\n"));
771#endif
772#ifdef FEAT_GUI
773 /* Also write a message in the GUI window, if there is one. */
774 if (gui.in_use && !gui.dying && !gui.starting)
775 {
776 p = (char_u *)_("Reading from stdin...");
777 gui_write(p, (int)STRLEN(p));
778 }
779#endif
780 }
781 else if (!read_buffer)
782 filemess(curbuf, sfname, (char_u *)"", 0);
783 }
784
785 msg_scroll = FALSE; /* overwrite the file message */
786
787 /*
788 * Set linecnt now, before the "retry" caused by a wrong guess for
789 * fileformat, and after the autocommands, which may change them.
790 */
791 linecnt = curbuf->b_ml.ml_line_count;
792
793#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000794 /* "++bad=" argument. */
795 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000796 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000797 bad_char_behavior = eap->bad_char;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000798 if (set_options)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000799 curbuf->b_bad_char = eap->bad_char;
800 }
801 else
802 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000803
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000805 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 */
807 if (eap != NULL && eap->force_enc != 0)
808 {
809 fenc = enc_canonize(eap->cmd + eap->force_enc);
810 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000811 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812 }
813 else if (curbuf->b_p_bin)
814 {
815 fenc = (char_u *)""; /* binary: don't convert */
816 fenc_alloced = FALSE;
817 }
818 else if (curbuf->b_help)
819 {
820 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000821 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822
823 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
824 * fails it must be latin1.
825 * Always do this when 'encoding' is "utf-8". Otherwise only do
826 * this when needed to avoid [converted] remarks all the time.
827 * It is needed when the first line contains non-ASCII characters.
828 * That is only in *.??x files. */
829 fenc = (char_u *)"latin1";
830 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000831 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000833 fc = fname[STRLEN(fname) - 1];
834 if (TOLOWER_ASC(fc) == 'x')
835 {
836 /* Read the first line (and a bit more). Immediately rewind to
837 * the start of the file. If the read() fails "len" is -1. */
838 len = vim_read(fd, firstline, 80);
839 lseek(fd, (off_t)0L, SEEK_SET);
840 for (p = firstline; p < firstline + len; ++p)
841 if (*p >= 0x80)
842 {
843 c = TRUE;
844 break;
845 }
846 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 }
848
849 if (c)
850 {
851 fenc_next = fenc;
852 fenc = (char_u *)"utf-8";
853
854 /* When the file is utf-8 but a character doesn't fit in
855 * 'encoding' don't retry. In help text editing utf-8 bytes
856 * doesn't make sense. */
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000857 if (!enc_utf8)
858 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 }
860 fenc_alloced = FALSE;
861 }
862 else if (*p_fencs == NUL)
863 {
864 fenc = curbuf->b_p_fenc; /* use format from buffer */
865 fenc_alloced = FALSE;
866 }
867 else
868 {
869 fenc_next = p_fencs; /* try items in 'fileencodings' */
870 fenc = next_fenc(&fenc_next);
871 fenc_alloced = TRUE;
872 }
873#endif
874
875 /*
876 * Jump back here to retry reading the file in different ways.
877 * Reasons to retry:
878 * - encoding conversion failed: try another one from "fenc_next"
879 * - BOM detected and fenc was set, need to setup conversion
880 * - "fileformat" check failed: try another
881 *
882 * Variables set for special retry actions:
883 * "file_rewind" Rewind the file to start reading it again.
884 * "advance_fenc" Advance "fenc" using "fenc_next".
885 * "skip_read" Re-use already read bytes (BOM detected).
886 * "did_iconv" iconv() conversion failed, try 'charconvert'.
887 * "keep_fileformat" Don't reset "fileformat".
888 *
889 * Other status indicators:
890 * "tmpname" When != NULL did conversion with 'charconvert'.
891 * Output file has to be deleted afterwards.
892 * "iconv_fd" When != -1 did conversion with iconv().
893 */
894retry:
895
896 if (file_rewind)
897 {
898 if (read_buffer)
899 {
900 read_buf_lnum = 1;
901 read_buf_col = 0;
902 }
903 else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
904 {
905 /* Can't rewind the file, give up. */
906 error = TRUE;
907 goto failed;
908 }
909 /* Delete the previously read lines. */
910 while (lnum > from)
911 ml_delete(lnum--, FALSE);
912 file_rewind = FALSE;
913#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000914 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 curbuf->b_p_bomb = FALSE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000916 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917#endif
918 }
919
920 /*
921 * When retrying with another "fenc" and the first time "fileformat"
922 * will be reset.
923 */
924 if (keep_fileformat)
925 keep_fileformat = FALSE;
926 else
927 {
928 if (eap != NULL && eap->force_ff != 0)
929 fileformat = get_fileformat_force(curbuf, eap);
930 else if (curbuf->b_p_bin)
931 fileformat = EOL_UNIX; /* binary: use Unix format */
932 else if (*p_ffs == NUL)
933 fileformat = get_fileformat(curbuf);/* use format from buffer */
934 else
935 fileformat = EOL_UNKNOWN; /* detect from file */
936 }
937
938#ifdef FEAT_MBYTE
939# ifdef USE_ICONV
940 if (iconv_fd != (iconv_t)-1)
941 {
942 /* aborted conversion with iconv(), close the descriptor */
943 iconv_close(iconv_fd);
944 iconv_fd = (iconv_t)-1;
945 }
946# endif
947
948 if (advance_fenc)
949 {
950 /*
951 * Try the next entry in 'fileencodings'.
952 */
953 advance_fenc = FALSE;
954
955 if (eap != NULL && eap->force_enc != 0)
956 {
957 /* Conversion given with "++cc=" wasn't possible, read
958 * without conversion. */
959 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000960 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000961 if (fenc_alloced)
962 vim_free(fenc);
963 fenc = (char_u *)"";
964 fenc_alloced = FALSE;
965 }
966 else
967 {
968 if (fenc_alloced)
969 vim_free(fenc);
970 if (fenc_next != NULL)
971 {
972 fenc = next_fenc(&fenc_next);
973 fenc_alloced = (fenc_next != NULL);
974 }
975 else
976 {
977 fenc = (char_u *)"";
978 fenc_alloced = FALSE;
979 }
980 }
981 if (tmpname != NULL)
982 {
983 mch_remove(tmpname); /* delete converted file */
984 vim_free(tmpname);
985 tmpname = NULL;
986 }
987 }
988
989 /*
990 * Conversion is required when the encoding of the file is different
991 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4 (requires
992 * conversion to UTF-8).
993 */
994 fio_flags = 0;
995 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
996 if (converted || enc_unicode != 0)
997 {
998
999 /* "ucs-bom" means we need to check the first bytes of the file
1000 * for a BOM. */
1001 if (STRCMP(fenc, ENC_UCSBOM) == 0)
1002 fio_flags = FIO_UCSBOM;
1003
1004 /*
1005 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
1006 * done. This is handled below after read(). Prepare the
1007 * fio_flags to avoid having to parse the string each time.
1008 * Also check for Unicode to Latin1 conversion, because iconv()
1009 * appears not to handle this correctly. This works just like
1010 * conversion to UTF-8 except how the resulting character is put in
1011 * the buffer.
1012 */
1013 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
1014 fio_flags = get_fio_flags(fenc);
1015
1016# ifdef WIN3264
1017 /*
1018 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
1019 * is handled with MultiByteToWideChar().
1020 */
1021 if (fio_flags == 0)
1022 fio_flags = get_win_fio_flags(fenc);
1023# endif
1024
1025# ifdef MACOS_X
1026 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
1027 if (fio_flags == 0)
1028 fio_flags = get_mac_fio_flags(fenc);
1029# endif
1030
1031# ifdef USE_ICONV
1032 /*
1033 * Try using iconv() if we can't convert internally.
1034 */
1035 if (fio_flags == 0
1036# ifdef FEAT_EVAL
1037 && !did_iconv
1038# endif
1039 )
1040 iconv_fd = (iconv_t)my_iconv_open(
1041 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
1042# endif
1043
1044# ifdef FEAT_EVAL
1045 /*
1046 * Use the 'charconvert' expression when conversion is required
1047 * and we can't do it internally or with iconv().
1048 */
1049 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1050# ifdef USE_ICONV
1051 && iconv_fd == (iconv_t)-1
1052# endif
1053 )
1054 {
1055# ifdef USE_ICONV
1056 did_iconv = FALSE;
1057# endif
1058 /* Skip conversion when it's already done (retry for wrong
1059 * "fileformat"). */
1060 if (tmpname == NULL)
1061 {
1062 tmpname = readfile_charconvert(fname, fenc, &fd);
1063 if (tmpname == NULL)
1064 {
1065 /* Conversion failed. Try another one. */
1066 advance_fenc = TRUE;
1067 if (fd < 0)
1068 {
1069 /* Re-opening the original file failed! */
1070 EMSG(_("E202: Conversion made file unreadable!"));
1071 error = TRUE;
1072 goto failed;
1073 }
1074 goto retry;
1075 }
1076 }
1077 }
1078 else
1079# endif
1080 {
1081 if (fio_flags == 0
1082# ifdef USE_ICONV
1083 && iconv_fd == (iconv_t)-1
1084# endif
1085 )
1086 {
1087 /* Conversion wanted but we can't.
1088 * Try the next conversion in 'fileencodings' */
1089 advance_fenc = TRUE;
1090 goto retry;
1091 }
1092 }
1093 }
1094
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001095 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001096 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001097 * stdin or fixed at a specific encoding. */
1098 can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099#endif
1100
1101 if (!skip_read)
1102 {
1103 linerest = 0;
1104 filesize = 0;
1105 skip_count = lines_to_skip;
1106 read_count = lines_to_read;
1107#ifdef FEAT_MBYTE
1108 conv_restlen = 0;
1109#endif
1110 }
1111
1112 while (!error && !got_int)
1113 {
1114 /*
1115 * We allocate as much space for the file as we can get, plus
1116 * space for the old line plus room for one terminating NUL.
1117 * The amount is limited by the fact that read() only can read
1118 * upto max_unsigned characters (and other things).
1119 */
1120#if SIZEOF_INT <= 2
1121 if (linerest >= 0x7ff0)
1122 {
1123 ++split;
1124 *ptr = NL; /* split line by inserting a NL */
1125 size = 1;
1126 }
1127 else
1128#endif
1129 {
1130 if (!skip_read)
1131 {
1132#if SIZEOF_INT > 2
Bram Moolenaar311d9822007-02-27 15:48:28 +00001133# if defined(SSIZE_MAX) && (SSIZE_MAX < 0x10000L)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001134 size = SSIZE_MAX; /* use max I/O size, 52K */
1135# else
1136 size = 0x10000L; /* use buffer >= 64K */
1137# endif
1138#else
1139 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1140#endif
1141
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001142 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001143 {
1144 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1145 FALSE)) != NULL)
1146 break;
1147 }
1148 if (new_buffer == NULL)
1149 {
1150 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1151 error = TRUE;
1152 break;
1153 }
1154 if (linerest) /* copy characters from the previous buffer */
1155 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1156 vim_free(buffer);
1157 buffer = new_buffer;
1158 ptr = buffer + linerest;
1159 line_start = buffer;
1160
1161#ifdef FEAT_MBYTE
1162 /* May need room to translate into.
1163 * For iconv() we don't really know the required space, use a
1164 * factor ICONV_MULT.
1165 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1166 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1167 * become up to 4 bytes, size must be multiple of 2
1168 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1169 * multiple of 2
1170 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1171 * multiple of 4 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001172 real_size = (int)size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173# ifdef USE_ICONV
1174 if (iconv_fd != (iconv_t)-1)
1175 size = size / ICONV_MULT;
1176 else
1177# endif
1178 if (fio_flags & FIO_LATIN1)
1179 size = size / 2;
1180 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1181 size = (size * 2 / 3) & ~1;
1182 else if (fio_flags & FIO_UCS4)
1183 size = (size * 2 / 3) & ~3;
1184 else if (fio_flags == FIO_UCSBOM)
1185 size = size / ICONV_MULT; /* worst case */
1186# ifdef WIN3264
1187 else if (fio_flags & FIO_CODEPAGE)
1188 size = size / ICONV_MULT; /* also worst case */
1189# endif
1190# ifdef MACOS_X
1191 else if (fio_flags & FIO_MACROMAN)
1192 size = size / ICONV_MULT; /* also worst case */
1193# endif
1194#endif
1195
1196#ifdef FEAT_MBYTE
1197 if (conv_restlen > 0)
1198 {
1199 /* Insert unconverted bytes from previous line. */
1200 mch_memmove(ptr, conv_rest, conv_restlen);
1201 ptr += conv_restlen;
1202 size -= conv_restlen;
1203 }
1204#endif
1205
1206 if (read_buffer)
1207 {
1208 /*
1209 * Read bytes from curbuf. Used for converting text read
1210 * from stdin.
1211 */
1212 if (read_buf_lnum > from)
1213 size = 0;
1214 else
1215 {
1216 int n, ni;
1217 long tlen;
1218
1219 tlen = 0;
1220 for (;;)
1221 {
1222 p = ml_get(read_buf_lnum) + read_buf_col;
1223 n = (int)STRLEN(p);
1224 if ((int)tlen + n + 1 > size)
1225 {
1226 /* Filled up to "size", append partial line.
1227 * Change NL to NUL to reverse the effect done
1228 * below. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001229 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001230 for (ni = 0; ni < n; ++ni)
1231 {
1232 if (p[ni] == NL)
1233 ptr[tlen++] = NUL;
1234 else
1235 ptr[tlen++] = p[ni];
1236 }
1237 read_buf_col += n;
1238 break;
1239 }
1240 else
1241 {
1242 /* Append whole line and new-line. Change NL
1243 * to NUL to reverse the effect done below. */
1244 for (ni = 0; ni < n; ++ni)
1245 {
1246 if (p[ni] == NL)
1247 ptr[tlen++] = NUL;
1248 else
1249 ptr[tlen++] = p[ni];
1250 }
1251 ptr[tlen++] = NL;
1252 read_buf_col = 0;
1253 if (++read_buf_lnum > from)
1254 {
1255 /* When the last line didn't have an
1256 * end-of-line don't add it now either. */
1257 if (!curbuf->b_p_eol)
1258 --tlen;
1259 size = tlen;
1260 break;
1261 }
1262 }
1263 }
1264 }
1265 }
1266 else
1267 {
1268 /*
1269 * Read bytes from the file.
1270 */
1271 size = vim_read(fd, ptr, size);
1272 }
1273
1274 if (size <= 0)
1275 {
1276 if (size < 0) /* read error */
1277 error = TRUE;
1278#ifdef FEAT_MBYTE
1279 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001280 {
1281 /* Reached end-of-file but some trailing bytes could
Bram Moolenaar7263a772007-05-10 17:35:54 +00001282 * not be converted. Truncated file? */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001283 if (conv_error == 0)
1284 conv_error = linecnt;
1285 if (bad_char_behavior != BAD_DROP)
1286 {
1287 fio_flags = 0; /* don't convert this */
Bram Moolenaarb21e5842006-04-16 18:30:08 +00001288# ifdef USE_ICONV
1289 if (iconv_fd != (iconv_t)-1)
1290 {
1291 iconv_close(iconv_fd);
1292 iconv_fd = (iconv_t)-1;
1293 }
1294# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001295 if (bad_char_behavior == BAD_KEEP)
1296 {
1297 /* Keep the trailing bytes as-is. */
1298 size = conv_restlen;
1299 ptr -= conv_restlen;
1300 }
1301 else
1302 {
1303 /* Replace the trailing bytes with the
1304 * replacement character. */
1305 size = 1;
1306 *--ptr = bad_char_behavior;
1307 }
1308 conv_restlen = 0;
1309 }
1310 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001311#endif
1312 }
1313
1314#ifdef FEAT_CRYPT
1315 /*
1316 * At start of file: Check for magic number of encryption.
1317 */
1318 if (filesize == 0)
1319 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
1320 &filesize, newfile);
1321 /*
1322 * Decrypt the read bytes.
1323 */
1324 if (cryptkey != NULL && size > 0)
1325 for (p = ptr; p < ptr + size; ++p)
1326 ZDECODE(*p);
1327#endif
1328 }
1329 skip_read = FALSE;
1330
1331#ifdef FEAT_MBYTE
1332 /*
1333 * At start of file (or after crypt magic number): Check for BOM.
1334 * Also check for a BOM for other Unicode encodings, but not after
1335 * converting with 'charconvert' or when a BOM has already been
1336 * found.
1337 */
1338 if ((filesize == 0
1339# ifdef FEAT_CRYPT
1340 || (filesize == CRYPT_MAGIC_LEN && cryptkey != NULL)
1341# endif
1342 )
1343 && (fio_flags == FIO_UCSBOM
1344 || (!curbuf->b_p_bomb
1345 && tmpname == NULL
1346 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1347 {
1348 char_u *ccname;
1349 int blen;
1350
1351 /* no BOM detection in a short file or in binary mode */
1352 if (size < 2 || curbuf->b_p_bin)
1353 ccname = NULL;
1354 else
1355 ccname = check_for_bom(ptr, size, &blen,
1356 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1357 if (ccname != NULL)
1358 {
1359 /* Remove BOM from the text */
1360 filesize += blen;
1361 size -= blen;
1362 mch_memmove(ptr, ptr + blen, (size_t)size);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001363 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001364 curbuf->b_p_bomb = TRUE;
1365 }
1366
1367 if (fio_flags == FIO_UCSBOM)
1368 {
1369 if (ccname == NULL)
1370 {
1371 /* No BOM detected: retry with next encoding. */
1372 advance_fenc = TRUE;
1373 }
1374 else
1375 {
1376 /* BOM detected: set "fenc" and jump back */
1377 if (fenc_alloced)
1378 vim_free(fenc);
1379 fenc = ccname;
1380 fenc_alloced = FALSE;
1381 }
1382 /* retry reading without getting new bytes or rewinding */
1383 skip_read = TRUE;
1384 goto retry;
1385 }
1386 }
1387#endif
1388 /*
1389 * Break here for a read error or end-of-file.
1390 */
1391 if (size <= 0)
1392 break;
1393
1394#ifdef FEAT_MBYTE
1395
1396 /* Include not converted bytes. */
1397 ptr -= conv_restlen;
1398 size += conv_restlen;
1399 conv_restlen = 0;
1400
1401# ifdef USE_ICONV
1402 if (iconv_fd != (iconv_t)-1)
1403 {
1404 /*
1405 * Attempt conversion of the read bytes to 'encoding' using
1406 * iconv().
1407 */
1408 const char *fromp;
1409 char *top;
1410 size_t from_size;
1411 size_t to_size;
1412
1413 fromp = (char *)ptr;
1414 from_size = size;
1415 ptr += size;
1416 top = (char *)ptr;
1417 to_size = real_size - size;
1418
1419 /*
1420 * If there is conversion error or not enough room try using
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001421 * another conversion. Except for when there is no
1422 * alternative (help files).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001423 */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001424 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1425 &top, &to_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001426 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1427 || from_size > CONV_RESTLEN)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001428 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001429 if (can_retry)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001430 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001431 if (conv_error == 0)
1432 conv_error = readfile_linenr(linecnt,
1433 ptr, (char_u *)top);
Bram Moolenaar42eeac32005-06-29 22:40:58 +00001434
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001435 /* Deal with a bad byte and continue with the next. */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001436 ++fromp;
1437 --from_size;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001438 if (bad_char_behavior == BAD_KEEP)
1439 {
1440 *top++ = *(fromp - 1);
1441 --to_size;
1442 }
1443 else if (bad_char_behavior != BAD_DROP)
1444 {
1445 *top++ = bad_char_behavior;
1446 --to_size;
1447 }
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001448 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001449
1450 if (from_size > 0)
1451 {
1452 /* Some remaining characters, keep them for the next
1453 * round. */
1454 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1455 conv_restlen = (int)from_size;
1456 }
1457
1458 /* move the linerest to before the converted characters */
1459 line_start = ptr - linerest;
1460 mch_memmove(line_start, buffer, (size_t)linerest);
1461 size = (long)((char_u *)top - ptr);
1462 }
1463# endif
1464
1465# ifdef WIN3264
1466 if (fio_flags & FIO_CODEPAGE)
1467 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001468 char_u *src, *dst;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001469 WCHAR ucs2buf[3];
1470 int ucs2len;
1471 int codepage = FIO_GET_CP(fio_flags);
1472 int bytelen;
1473 int found_bad;
1474 char replstr[2];
1475
Bram Moolenaar071d4272004-06-13 20:20:40 +00001476 /*
1477 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001478 * a codepage, using standard MS-Windows functions. This
1479 * requires two steps:
1480 * 1. convert from 'fileencoding' to ucs-2
1481 * 2. convert from ucs-2 to 'encoding'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001482 *
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001483 * Because there may be illegal bytes AND an incomplete byte
1484 * sequence at the end, we may have to do the conversion one
1485 * character at a time to get it right.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001486 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001487
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001488 /* Replacement string for WideCharToMultiByte(). */
1489 if (bad_char_behavior > 0)
1490 replstr[0] = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491 else
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001492 replstr[0] = '?';
1493 replstr[1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001494
1495 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001496 * Move the bytes to the end of the buffer, so that we have
1497 * room to put the result at the start.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001498 */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001499 src = ptr + real_size - size;
1500 mch_memmove(src, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001501
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001502 /*
1503 * Do the conversion.
1504 */
1505 dst = ptr;
1506 size = size;
1507 while (size > 0)
1508 {
1509 found_bad = FALSE;
1510
1511# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1512 if (codepage == CP_UTF8)
1513 {
1514 /* Handle CP_UTF8 input ourselves to be able to handle
1515 * trailing bytes properly.
1516 * Get one UTF-8 character from src. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001517 bytelen = (int)utf_ptr2len_len(src, size);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001518 if (bytelen > size)
1519 {
1520 /* Only got some bytes of a character. Normally
1521 * it's put in "conv_rest", but if it's too long
1522 * deal with it as if they were illegal bytes. */
1523 if (bytelen <= CONV_RESTLEN)
1524 break;
1525
1526 /* weird overlong byte sequence */
1527 bytelen = size;
1528 found_bad = TRUE;
1529 }
1530 else
1531 {
Bram Moolenaarc01140a2006-03-24 22:21:52 +00001532 int u8c = utf_ptr2char(src);
1533
Bram Moolenaar86e01082005-12-29 22:45:34 +00001534 if (u8c > 0xffff || (*src >= 0x80 && bytelen == 1))
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001535 found_bad = TRUE;
1536 ucs2buf[0] = u8c;
1537 ucs2len = 1;
1538 }
1539 }
1540 else
1541# endif
1542 {
1543 /* We don't know how long the byte sequence is, try
1544 * from one to three bytes. */
1545 for (bytelen = 1; bytelen <= size && bytelen <= 3;
1546 ++bytelen)
1547 {
1548 ucs2len = MultiByteToWideChar(codepage,
1549 MB_ERR_INVALID_CHARS,
1550 (LPCSTR)src, bytelen,
1551 ucs2buf, 3);
1552 if (ucs2len > 0)
1553 break;
1554 }
1555 if (ucs2len == 0)
1556 {
1557 /* If we have only one byte then it's probably an
1558 * incomplete byte sequence. Otherwise discard
1559 * one byte as a bad character. */
1560 if (size == 1)
1561 break;
1562 found_bad = TRUE;
1563 bytelen = 1;
1564 }
1565 }
1566
1567 if (!found_bad)
1568 {
1569 int i;
1570
1571 /* Convert "ucs2buf[ucs2len]" to 'enc' in "dst". */
1572 if (enc_utf8)
1573 {
1574 /* From UCS-2 to UTF-8. Cannot fail. */
1575 for (i = 0; i < ucs2len; ++i)
1576 dst += utf_char2bytes(ucs2buf[i], dst);
1577 }
1578 else
1579 {
1580 BOOL bad = FALSE;
1581 int dstlen;
1582
1583 /* From UCS-2 to "enc_codepage". If the
1584 * conversion uses the default character "?",
1585 * the data doesn't fit in this encoding. */
1586 dstlen = WideCharToMultiByte(enc_codepage, 0,
1587 (LPCWSTR)ucs2buf, ucs2len,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001588 (LPSTR)dst, (int)(src - dst),
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001589 replstr, &bad);
1590 if (bad)
1591 found_bad = TRUE;
1592 else
1593 dst += dstlen;
1594 }
1595 }
1596
1597 if (found_bad)
1598 {
1599 /* Deal with bytes we can't convert. */
1600 if (can_retry)
1601 goto rewind_retry;
1602 if (conv_error == 0)
1603 conv_error = readfile_linenr(linecnt, ptr, dst);
1604 if (bad_char_behavior != BAD_DROP)
1605 {
1606 if (bad_char_behavior == BAD_KEEP)
1607 {
1608 mch_memmove(dst, src, bytelen);
1609 dst += bytelen;
1610 }
1611 else
1612 *dst++ = bad_char_behavior;
1613 }
1614 }
1615
1616 src += bytelen;
1617 size -= bytelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001618 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001619
1620 if (size > 0)
1621 {
1622 /* An incomplete byte sequence remaining. */
1623 mch_memmove(conv_rest, src, size);
1624 conv_restlen = size;
1625 }
1626
1627 /* The new size is equal to how much "dst" was advanced. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001628 size = (long)(dst - ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001629 }
1630 else
1631# endif
Bram Moolenaar56718732006-03-15 22:53:57 +00001632# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001633 if (fio_flags & FIO_MACROMAN)
1634 {
1635 /*
1636 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001637 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001638 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001639 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001640 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641 }
1642 else
1643# endif
1644 if (fio_flags != 0)
1645 {
1646 int u8c;
1647 char_u *dest;
1648 char_u *tail = NULL;
1649
1650 /*
1651 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1652 * "enc_utf8" not set: Convert Unicode to Latin1.
1653 * Go from end to start through the buffer, because the number
1654 * of bytes may increase.
1655 * "dest" points to after where the UTF-8 bytes go, "p" points
1656 * to after the next character to convert.
1657 */
1658 dest = ptr + real_size;
1659 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1660 {
1661 p = ptr + size;
1662 if (fio_flags == FIO_UTF8)
1663 {
1664 /* Check for a trailing incomplete UTF-8 sequence */
1665 tail = ptr + size - 1;
1666 while (tail > ptr && (*tail & 0xc0) == 0x80)
1667 --tail;
1668 if (tail + utf_byte2len(*tail) <= ptr + size)
1669 tail = NULL;
1670 else
1671 p = tail;
1672 }
1673 }
1674 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1675 {
1676 /* Check for a trailing byte */
1677 p = ptr + (size & ~1);
1678 if (size & 1)
1679 tail = p;
1680 if ((fio_flags & FIO_UTF16) && p > ptr)
1681 {
1682 /* Check for a trailing leading word */
1683 if (fio_flags & FIO_ENDIAN_L)
1684 {
1685 u8c = (*--p << 8);
1686 u8c += *--p;
1687 }
1688 else
1689 {
1690 u8c = *--p;
1691 u8c += (*--p << 8);
1692 }
1693 if (u8c >= 0xd800 && u8c <= 0xdbff)
1694 tail = p;
1695 else
1696 p += 2;
1697 }
1698 }
1699 else /* FIO_UCS4 */
1700 {
1701 /* Check for trailing 1, 2 or 3 bytes */
1702 p = ptr + (size & ~3);
1703 if (size & 3)
1704 tail = p;
1705 }
1706
1707 /* If there is a trailing incomplete sequence move it to
1708 * conv_rest[]. */
1709 if (tail != NULL)
1710 {
1711 conv_restlen = (int)((ptr + size) - tail);
1712 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1713 size -= conv_restlen;
1714 }
1715
1716
1717 while (p > ptr)
1718 {
1719 if (fio_flags & FIO_LATIN1)
1720 u8c = *--p;
1721 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1722 {
1723 if (fio_flags & FIO_ENDIAN_L)
1724 {
1725 u8c = (*--p << 8);
1726 u8c += *--p;
1727 }
1728 else
1729 {
1730 u8c = *--p;
1731 u8c += (*--p << 8);
1732 }
1733 if ((fio_flags & FIO_UTF16)
1734 && u8c >= 0xdc00 && u8c <= 0xdfff)
1735 {
1736 int u16c;
1737
1738 if (p == ptr)
1739 {
1740 /* Missing leading word. */
1741 if (can_retry)
1742 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001743 if (conv_error == 0)
1744 conv_error = readfile_linenr(linecnt,
1745 ptr, p);
1746 if (bad_char_behavior == BAD_DROP)
1747 continue;
1748 if (bad_char_behavior != BAD_KEEP)
1749 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001750 }
1751
1752 /* found second word of double-word, get the first
1753 * word and compute the resulting character */
1754 if (fio_flags & FIO_ENDIAN_L)
1755 {
1756 u16c = (*--p << 8);
1757 u16c += *--p;
1758 }
1759 else
1760 {
1761 u16c = *--p;
1762 u16c += (*--p << 8);
1763 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001764 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1765 + (u8c & 0x3ff);
1766
Bram Moolenaar071d4272004-06-13 20:20:40 +00001767 /* Check if the word is indeed a leading word. */
1768 if (u16c < 0xd800 || u16c > 0xdbff)
1769 {
1770 if (can_retry)
1771 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001772 if (conv_error == 0)
1773 conv_error = readfile_linenr(linecnt,
1774 ptr, p);
1775 if (bad_char_behavior == BAD_DROP)
1776 continue;
1777 if (bad_char_behavior != BAD_KEEP)
1778 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001780 }
1781 }
1782 else if (fio_flags & FIO_UCS4)
1783 {
1784 if (fio_flags & FIO_ENDIAN_L)
1785 {
1786 u8c = (*--p << 24);
1787 u8c += (*--p << 16);
1788 u8c += (*--p << 8);
1789 u8c += *--p;
1790 }
1791 else /* big endian */
1792 {
1793 u8c = *--p;
1794 u8c += (*--p << 8);
1795 u8c += (*--p << 16);
1796 u8c += (*--p << 24);
1797 }
1798 }
1799 else /* UTF-8 */
1800 {
1801 if (*--p < 0x80)
1802 u8c = *p;
1803 else
1804 {
1805 len = utf_head_off(ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001806 p -= len;
1807 u8c = utf_ptr2char(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001808 if (len == 0)
1809 {
1810 /* Not a valid UTF-8 character, retry with
1811 * another fenc when possible, otherwise just
1812 * report the error. */
1813 if (can_retry)
1814 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001815 if (conv_error == 0)
1816 conv_error = readfile_linenr(linecnt,
1817 ptr, p);
1818 if (bad_char_behavior == BAD_DROP)
1819 continue;
1820 if (bad_char_behavior != BAD_KEEP)
1821 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001822 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001823 }
1824 }
1825 if (enc_utf8) /* produce UTF-8 */
1826 {
1827 dest -= utf_char2len(u8c);
1828 (void)utf_char2bytes(u8c, dest);
1829 }
1830 else /* produce Latin1 */
1831 {
1832 --dest;
1833 if (u8c >= 0x100)
1834 {
1835 /* character doesn't fit in latin1, retry with
1836 * another fenc when possible, otherwise just
1837 * report the error. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001838 if (can_retry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001839 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001840 if (conv_error == 0)
1841 conv_error = readfile_linenr(linecnt, ptr, p);
1842 if (bad_char_behavior == BAD_DROP)
1843 ++dest;
1844 else if (bad_char_behavior == BAD_KEEP)
1845 *dest = u8c;
1846 else if (eap != NULL && eap->bad_char != 0)
1847 *dest = bad_char_behavior;
1848 else
1849 *dest = 0xBF;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001850 }
1851 else
1852 *dest = u8c;
1853 }
1854 }
1855
1856 /* move the linerest to before the converted characters */
1857 line_start = dest - linerest;
1858 mch_memmove(line_start, buffer, (size_t)linerest);
1859 size = (long)((ptr + real_size) - dest);
1860 ptr = dest;
1861 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001862 else if (enc_utf8 && conv_error == 0 && !curbuf->b_p_bin)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 {
1864 /* Reading UTF-8: Check if the bytes are valid UTF-8.
1865 * Need to start before "ptr" when part of the character was
1866 * read in the previous read() call. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001867 for (p = ptr - utf_head_off(buffer, ptr); ; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001868 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001869 int todo = (int)((ptr + size) - p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001870 int l;
1871
1872 if (todo <= 0)
1873 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874 if (*p >= 0x80)
1875 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 /* A length of 1 means it's an illegal byte. Accept
1877 * an incomplete character at the end though, the next
1878 * read() will get the next bytes, we'll check it
1879 * then. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001880 l = utf_ptr2len_len(p, todo);
1881 if (l > todo)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001882 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001883 /* Incomplete byte sequence, the next read()
1884 * should get them and check the bytes. */
1885 p += todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001886 break;
1887 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001888 if (l == 1)
1889 {
1890 /* Illegal byte. If we can try another encoding
1891 * do that. */
1892 if (can_retry)
1893 break;
1894
1895 /* Remember the first linenr with an illegal byte */
1896 if (illegal_byte == 0)
1897 illegal_byte = readfile_linenr(linecnt, ptr, p);
1898# ifdef USE_ICONV
1899 /* When we did a conversion report an error. */
1900 if (iconv_fd != (iconv_t)-1 && conv_error == 0)
1901 conv_error = readfile_linenr(linecnt, ptr, p);
1902# endif
1903
1904 /* Drop, keep or replace the bad byte. */
1905 if (bad_char_behavior == BAD_DROP)
1906 {
1907 mch_memmove(p, p+1, todo - 1);
1908 --p;
1909 --size;
1910 }
1911 else if (bad_char_behavior != BAD_KEEP)
1912 *p = bad_char_behavior;
1913 }
1914 p += l - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001915 }
1916 }
1917 if (p < ptr + size)
1918 {
1919 /* Detected a UTF-8 error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920rewind_retry:
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001921 /* Retry reading with another conversion. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001922# if defined(FEAT_EVAL) && defined(USE_ICONV)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001923 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
1924 /* iconv() failed, try 'charconvert' */
1925 did_iconv = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001926 else
1927# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001928 /* use next item from 'fileencodings' */
1929 advance_fenc = TRUE;
1930 file_rewind = TRUE;
1931 goto retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001932 }
1933 }
1934#endif
1935
1936 /* count the number of characters (after conversion!) */
1937 filesize += size;
1938
1939 /*
1940 * when reading the first part of a file: guess EOL type
1941 */
1942 if (fileformat == EOL_UNKNOWN)
1943 {
1944 /* First try finding a NL, for Dos and Unix */
1945 if (try_dos || try_unix)
1946 {
1947 for (p = ptr; p < ptr + size; ++p)
1948 {
1949 if (*p == NL)
1950 {
1951 if (!try_unix
1952 || (try_dos && p > ptr && p[-1] == CAR))
1953 fileformat = EOL_DOS;
1954 else
1955 fileformat = EOL_UNIX;
1956 break;
1957 }
1958 }
1959
1960 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
1961 if (fileformat == EOL_UNIX && try_mac)
1962 {
1963 /* Need to reset the counters when retrying fenc. */
1964 try_mac = 1;
1965 try_unix = 1;
1966 for (; p >= ptr && *p != CAR; p--)
1967 ;
1968 if (p >= ptr)
1969 {
1970 for (p = ptr; p < ptr + size; ++p)
1971 {
1972 if (*p == NL)
1973 try_unix++;
1974 else if (*p == CAR)
1975 try_mac++;
1976 }
1977 if (try_mac > try_unix)
1978 fileformat = EOL_MAC;
1979 }
1980 }
1981 }
1982
1983 /* No NL found: may use Mac format */
1984 if (fileformat == EOL_UNKNOWN && try_mac)
1985 fileformat = EOL_MAC;
1986
1987 /* Still nothing found? Use first format in 'ffs' */
1988 if (fileformat == EOL_UNKNOWN)
1989 fileformat = default_fileformat();
1990
1991 /* if editing a new file: may set p_tx and p_ff */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001992 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001993 set_fileformat(fileformat, OPT_LOCAL);
1994 }
1995 }
1996
1997 /*
1998 * This loop is executed once for every character read.
1999 * Keep it fast!
2000 */
2001 if (fileformat == EOL_MAC)
2002 {
2003 --ptr;
2004 while (++ptr, --size >= 0)
2005 {
2006 /* catch most common case first */
2007 if ((c = *ptr) != NUL && c != CAR && c != NL)
2008 continue;
2009 if (c == NUL)
2010 *ptr = NL; /* NULs are replaced by newlines! */
2011 else if (c == NL)
2012 *ptr = CAR; /* NLs are replaced by CRs! */
2013 else
2014 {
2015 if (skip_count == 0)
2016 {
2017 *ptr = NUL; /* end of line */
2018 len = (colnr_T) (ptr - line_start + 1);
2019 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2020 {
2021 error = TRUE;
2022 break;
2023 }
2024 ++lnum;
2025 if (--read_count == 0)
2026 {
2027 error = TRUE; /* break loop */
2028 line_start = ptr; /* nothing left to write */
2029 break;
2030 }
2031 }
2032 else
2033 --skip_count;
2034 line_start = ptr + 1;
2035 }
2036 }
2037 }
2038 else
2039 {
2040 --ptr;
2041 while (++ptr, --size >= 0)
2042 {
2043 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2044 continue;
2045 if (c == NUL)
2046 *ptr = NL; /* NULs are replaced by newlines! */
2047 else
2048 {
2049 if (skip_count == 0)
2050 {
2051 *ptr = NUL; /* end of line */
2052 len = (colnr_T)(ptr - line_start + 1);
2053 if (fileformat == EOL_DOS)
2054 {
2055 if (ptr[-1] == CAR) /* remove CR */
2056 {
2057 ptr[-1] = NUL;
2058 --len;
2059 }
2060 /*
2061 * Reading in Dos format, but no CR-LF found!
2062 * When 'fileformats' includes "unix", delete all
2063 * the lines read so far and start all over again.
2064 * Otherwise give an error message later.
2065 */
2066 else if (ff_error != EOL_DOS)
2067 {
2068 if ( try_unix
2069 && !read_stdin
2070 && (read_buffer
2071 || lseek(fd, (off_t)0L, SEEK_SET) == 0))
2072 {
2073 fileformat = EOL_UNIX;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002074 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002075 set_fileformat(EOL_UNIX, OPT_LOCAL);
2076 file_rewind = TRUE;
2077 keep_fileformat = TRUE;
2078 goto retry;
2079 }
2080 ff_error = EOL_DOS;
2081 }
2082 }
2083 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2084 {
2085 error = TRUE;
2086 break;
2087 }
2088 ++lnum;
2089 if (--read_count == 0)
2090 {
2091 error = TRUE; /* break loop */
2092 line_start = ptr; /* nothing left to write */
2093 break;
2094 }
2095 }
2096 else
2097 --skip_count;
2098 line_start = ptr + 1;
2099 }
2100 }
2101 }
2102 linerest = (long)(ptr - line_start);
2103 ui_breakcheck();
2104 }
2105
2106failed:
2107 /* not an error, max. number of lines reached */
2108 if (error && read_count == 0)
2109 error = FALSE;
2110
2111 /*
2112 * If we get EOF in the middle of a line, note the fact and
2113 * complete the line ourselves.
2114 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2115 */
2116 if (!error
2117 && !got_int
2118 && linerest != 0
2119 && !(!curbuf->b_p_bin
2120 && fileformat == EOL_DOS
2121 && *line_start == Ctrl_Z
2122 && ptr == line_start + 1))
2123 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002124 /* remember for when writing */
2125 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002126 curbuf->b_p_eol = FALSE;
2127 *ptr = NUL;
2128 if (ml_append(lnum, line_start,
2129 (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
2130 error = TRUE;
2131 else
2132 read_no_eol_lnum = ++lnum;
2133 }
2134
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002135 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002136 save_file_ff(curbuf); /* remember the current file format */
2137
2138#ifdef FEAT_CRYPT
2139 if (cryptkey != curbuf->b_p_key)
2140 vim_free(cryptkey);
2141#endif
2142
2143#ifdef FEAT_MBYTE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002144 /* If editing a new file: set 'fenc' for the current buffer.
2145 * Also for ":read ++edit file". */
2146 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002147 set_string_option_direct((char_u *)"fenc", -1, fenc,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002148 OPT_FREE|OPT_LOCAL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002149 if (fenc_alloced)
2150 vim_free(fenc);
2151# ifdef USE_ICONV
2152 if (iconv_fd != (iconv_t)-1)
2153 {
2154 iconv_close(iconv_fd);
2155 iconv_fd = (iconv_t)-1;
2156 }
2157# endif
2158#endif
2159
2160 if (!read_buffer && !read_stdin)
2161 close(fd); /* errors are ignored */
2162 vim_free(buffer);
2163
2164#ifdef HAVE_DUP
2165 if (read_stdin)
2166 {
2167 /* Use stderr for stdin, makes shell commands work. */
2168 close(0);
2169 dup(2);
2170 }
2171#endif
2172
2173#ifdef FEAT_MBYTE
2174 if (tmpname != NULL)
2175 {
2176 mch_remove(tmpname); /* delete converted file */
2177 vim_free(tmpname);
2178 }
2179#endif
2180 --no_wait_return; /* may wait for return now */
2181
2182 /*
2183 * In recovery mode everything but autocommands is skipped.
2184 */
2185 if (!recoverymode)
2186 {
2187 /* need to delete the last line, which comes from the empty buffer */
2188 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2189 {
2190#ifdef FEAT_NETBEANS_INTG
2191 netbeansFireChanges = 0;
2192#endif
2193 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2194#ifdef FEAT_NETBEANS_INTG
2195 netbeansFireChanges = 1;
2196#endif
2197 --linecnt;
2198 }
2199 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2200 if (filesize == 0)
2201 linecnt = 0;
2202 if (newfile || read_buffer)
Bram Moolenaar7263a772007-05-10 17:35:54 +00002203 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar7263a772007-05-10 17:35:54 +00002205#ifdef FEAT_DIFF
2206 /* After reading the text into the buffer the diff info needs to
2207 * be updated. */
2208 diff_invalidate(curbuf);
2209#endif
2210#ifdef FEAT_FOLDING
2211 /* All folds in the window are invalid now. Mark them for update
2212 * before triggering autocommands. */
2213 foldUpdateAll(curwin);
2214#endif
2215 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002216 else if (linecnt) /* appended at least one line */
2217 appended_lines_mark(from, linecnt);
2218
Bram Moolenaar071d4272004-06-13 20:20:40 +00002219#ifndef ALWAYS_USE_GUI
2220 /*
2221 * If we were reading from the same terminal as where messages go,
2222 * the screen will have been messed up.
2223 * Switch on raw mode now and clear the screen.
2224 */
2225 if (read_stdin)
2226 {
2227 settmode(TMODE_RAW); /* set to raw mode */
2228 starttermcap();
2229 screenclear();
2230 }
2231#endif
2232
2233 if (got_int)
2234 {
2235 if (!(flags & READ_DUMMY))
2236 {
2237 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2238 if (newfile)
2239 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2240 }
2241 msg_scroll = msg_save;
2242#ifdef FEAT_VIMINFO
2243 check_marks_read();
2244#endif
2245 return OK; /* an interrupt isn't really an error */
2246 }
2247
2248 if (!filtering && !(flags & READ_DUMMY))
2249 {
2250 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2251 c = FALSE;
2252
2253#ifdef UNIX
2254# ifdef S_ISFIFO
2255 if (S_ISFIFO(perm)) /* fifo or socket */
2256 {
2257 STRCAT(IObuff, _("[fifo/socket]"));
2258 c = TRUE;
2259 }
2260# else
2261# ifdef S_IFIFO
2262 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2263 {
2264 STRCAT(IObuff, _("[fifo]"));
2265 c = TRUE;
2266 }
2267# endif
2268# ifdef S_IFSOCK
2269 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2270 {
2271 STRCAT(IObuff, _("[socket]"));
2272 c = TRUE;
2273 }
2274# endif
2275# endif
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002276# ifdef OPEN_CHR_FILES
2277 if (S_ISCHR(perm)) /* or character special */
2278 {
2279 STRCAT(IObuff, _("[character special]"));
2280 c = TRUE;
2281 }
2282# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002283#endif
2284 if (curbuf->b_p_ro)
2285 {
2286 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2287 c = TRUE;
2288 }
2289 if (read_no_eol_lnum)
2290 {
2291 msg_add_eol();
2292 c = TRUE;
2293 }
2294 if (ff_error == EOL_DOS)
2295 {
2296 STRCAT(IObuff, _("[CR missing]"));
2297 c = TRUE;
2298 }
2299 if (ff_error == EOL_MAC)
2300 {
2301 STRCAT(IObuff, _("[NL found]"));
2302 c = TRUE;
2303 }
2304 if (split)
2305 {
2306 STRCAT(IObuff, _("[long lines split]"));
2307 c = TRUE;
2308 }
2309#ifdef FEAT_MBYTE
2310 if (notconverted)
2311 {
2312 STRCAT(IObuff, _("[NOT converted]"));
2313 c = TRUE;
2314 }
2315 else if (converted)
2316 {
2317 STRCAT(IObuff, _("[converted]"));
2318 c = TRUE;
2319 }
2320#endif
2321#ifdef FEAT_CRYPT
2322 if (cryptkey != NULL)
2323 {
2324 STRCAT(IObuff, _("[crypted]"));
2325 c = TRUE;
2326 }
2327#endif
2328#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002329 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002330 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002331 sprintf((char *)IObuff + STRLEN(IObuff),
2332 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002333 c = TRUE;
2334 }
2335 else if (illegal_byte > 0)
2336 {
2337 sprintf((char *)IObuff + STRLEN(IObuff),
2338 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2339 c = TRUE;
2340 }
2341 else
2342#endif
2343 if (error)
2344 {
2345 STRCAT(IObuff, _("[READ ERRORS]"));
2346 c = TRUE;
2347 }
2348 if (msg_add_fileformat(fileformat))
2349 c = TRUE;
2350#ifdef FEAT_CRYPT
2351 if (cryptkey != NULL)
2352 msg_add_lines(c, (long)linecnt, filesize - CRYPT_MAGIC_LEN);
2353 else
2354#endif
2355 msg_add_lines(c, (long)linecnt, filesize);
2356
2357 vim_free(keep_msg);
2358 keep_msg = NULL;
2359 msg_scrolled_ign = TRUE;
2360#ifdef ALWAYS_USE_GUI
2361 /* Don't show the message when reading stdin, it would end up in a
2362 * message box (which might be shown when exiting!) */
2363 if (read_stdin || read_buffer)
2364 p = msg_may_trunc(FALSE, IObuff);
2365 else
2366#endif
2367 p = msg_trunc_attr(IObuff, FALSE, 0);
2368 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002369 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002370 /* Need to repeat the message after redrawing when:
2371 * - When reading from stdin (the screen will be cleared next).
2372 * - When restart_edit is set (otherwise there will be a delay
2373 * before redrawing).
2374 * - When the screen was scrolled but there is no wait-return
2375 * prompt. */
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002376 set_keep_msg(p, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002377 msg_scrolled_ign = FALSE;
2378 }
2379
2380 /* with errors writing the file requires ":w!" */
2381 if (newfile && (error
2382#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002383 || conv_error != 0
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00002384 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002385#endif
2386 ))
2387 curbuf->b_p_ro = TRUE;
2388
2389 u_clearline(); /* cannot use "U" command after adding lines */
2390
2391 /*
2392 * In Ex mode: cursor at last new line.
2393 * Otherwise: cursor at first new line.
2394 */
2395 if (exmode_active)
2396 curwin->w_cursor.lnum = from + linecnt;
2397 else
2398 curwin->w_cursor.lnum = from + 1;
2399 check_cursor_lnum();
2400 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2401
2402 /*
2403 * Set '[ and '] marks to the newly read lines.
2404 */
2405 curbuf->b_op_start.lnum = from + 1;
2406 curbuf->b_op_start.col = 0;
2407 curbuf->b_op_end.lnum = from + linecnt;
2408 curbuf->b_op_end.col = 0;
Bram Moolenaar03f48552006-02-28 23:52:23 +00002409
2410#ifdef WIN32
2411 /*
2412 * Work around a weird problem: When a file has two links (only
2413 * possible on NTFS) and we write through one link, then stat() it
2414 * throught the other link, the timestamp information may be wrong.
2415 * It's correct again after reading the file, thus reset the timestamp
2416 * here.
2417 */
2418 if (newfile && !read_stdin && !read_buffer
2419 && mch_stat((char *)fname, &st) >= 0)
2420 {
2421 buf_store_time(curbuf, &st, fname);
2422 curbuf->b_mtime_read = curbuf->b_mtime;
2423 }
2424#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002425 }
2426 msg_scroll = msg_save;
2427
2428#ifdef FEAT_VIMINFO
2429 /*
2430 * Get the marks before executing autocommands, so they can be used there.
2431 */
2432 check_marks_read();
2433#endif
2434
Bram Moolenaar071d4272004-06-13 20:20:40 +00002435 /*
2436 * Trick: We remember if the last line of the read didn't have
2437 * an eol for when writing it again. This is required for
2438 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
2439 */
2440 write_no_eol_lnum = read_no_eol_lnum;
2441
Bram Moolenaardf177f62005-02-22 08:39:57 +00002442#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00002443 if (!read_stdin && !read_buffer)
2444 {
2445 int m = msg_scroll;
2446 int n = msg_scrolled;
2447
2448 /* Save the fileformat now, otherwise the buffer will be considered
2449 * modified if the format/encoding was automatically detected. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002450 if (set_options)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002451 save_file_ff(curbuf);
2452
2453 /*
2454 * The output from the autocommands should not overwrite anything and
2455 * should not be overwritten: Set msg_scroll, restore its value if no
2456 * output was done.
2457 */
2458 msg_scroll = TRUE;
2459 if (filtering)
2460 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2461 FALSE, curbuf, eap);
2462 else if (newfile)
2463 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2464 FALSE, curbuf, eap);
2465 else
2466 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2467 FALSE, NULL, eap);
2468 if (msg_scrolled == n)
2469 msg_scroll = m;
2470#ifdef FEAT_EVAL
2471 if (aborting()) /* autocmds may abort script processing */
2472 return FAIL;
2473#endif
2474 }
2475#endif
2476
2477 if (recoverymode && error)
2478 return FAIL;
2479 return OK;
2480}
2481
Bram Moolenaarfe1c56d2007-07-10 15:10:54 +00002482#ifdef OPEN_CHR_FILES
2483/*
2484 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2485 * which is the name of files used for process substitution output by
2486 * some shells on some operating systems, e.g., bash on SunOS.
2487 * Do not accept "/dev/fd/[012]", opening these may hang Vim.
2488 */
2489 static int
2490is_dev_fd_file(fname)
2491 char_u *fname;
2492{
2493 return (STRNCMP(fname, "/dev/fd/", 8) == 0
2494 && VIM_ISDIGIT(fname[8])
2495 && *skipdigits(fname + 9) == NUL
2496 && (fname[9] != NUL
2497 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
2498}
2499#endif
2500
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002501#ifdef FEAT_MBYTE
2502
2503/*
2504 * From the current line count and characters read after that, estimate the
2505 * line number where we are now.
2506 * Used for error messages that include a line number.
2507 */
2508 static linenr_T
2509readfile_linenr(linecnt, p, endp)
2510 linenr_T linecnt; /* line count before reading more bytes */
2511 char_u *p; /* start of more bytes read */
2512 char_u *endp; /* end of more bytes read */
2513{
2514 char_u *s;
2515 linenr_T lnum;
2516
2517 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2518 for (s = p; s < endp; ++s)
2519 if (*s == '\n')
2520 ++lnum;
2521 return lnum;
2522}
2523#endif
2524
Bram Moolenaar071d4272004-06-13 20:20:40 +00002525/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002526 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2527 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528 * Returns OK or FAIL.
2529 */
2530 int
2531prep_exarg(eap, buf)
2532 exarg_T *eap;
2533 buf_T *buf;
2534{
2535 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2536#ifdef FEAT_MBYTE
2537 + STRLEN(buf->b_p_fenc)
2538#endif
2539 + 15));
2540 if (eap->cmd == NULL)
2541 return FAIL;
2542
2543#ifdef FEAT_MBYTE
2544 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2545 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
Bram Moolenaar195d6352005-12-19 22:08:24 +00002546 eap->bad_char = buf->b_bad_char;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002547#else
2548 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2549#endif
2550 eap->force_ff = 7;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002551
2552 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002553 eap->read_edit = FALSE;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002554 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002555 return OK;
2556}
2557
2558#ifdef FEAT_MBYTE
2559/*
2560 * Find next fileencoding to use from 'fileencodings'.
2561 * "pp" points to fenc_next. It's advanced to the next item.
2562 * When there are no more items, an empty string is returned and *pp is set to
2563 * NULL.
2564 * When *pp is not set to NULL, the result is in allocated memory.
2565 */
2566 static char_u *
2567next_fenc(pp)
2568 char_u **pp;
2569{
2570 char_u *p;
2571 char_u *r;
2572
2573 if (**pp == NUL)
2574 {
2575 *pp = NULL;
2576 return (char_u *)"";
2577 }
2578 p = vim_strchr(*pp, ',');
2579 if (p == NULL)
2580 {
2581 r = enc_canonize(*pp);
2582 *pp += STRLEN(*pp);
2583 }
2584 else
2585 {
2586 r = vim_strnsave(*pp, (int)(p - *pp));
2587 *pp = p + 1;
2588 if (r != NULL)
2589 {
2590 p = enc_canonize(r);
2591 vim_free(r);
2592 r = p;
2593 }
2594 }
2595 if (r == NULL) /* out of memory */
2596 {
2597 r = (char_u *)"";
2598 *pp = NULL;
2599 }
2600 return r;
2601}
2602
2603# ifdef FEAT_EVAL
2604/*
2605 * Convert a file with the 'charconvert' expression.
2606 * This closes the file which is to be read, converts it and opens the
2607 * resulting file for reading.
2608 * Returns name of the resulting converted file (the caller should delete it
2609 * after reading it).
2610 * Returns NULL if the conversion failed ("*fdp" is not set) .
2611 */
2612 static char_u *
2613readfile_charconvert(fname, fenc, fdp)
2614 char_u *fname; /* name of input file */
2615 char_u *fenc; /* converted from */
2616 int *fdp; /* in/out: file descriptor of file */
2617{
2618 char_u *tmpname;
2619 char_u *errmsg = NULL;
2620
2621 tmpname = vim_tempname('r');
2622 if (tmpname == NULL)
2623 errmsg = (char_u *)_("Can't find temp file for conversion");
2624 else
2625 {
2626 close(*fdp); /* close the input file, ignore errors */
2627 *fdp = -1;
2628 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2629 fname, tmpname) == FAIL)
2630 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2631 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2632 O_RDONLY | O_EXTRA, 0)) < 0)
2633 errmsg = (char_u *)_("can't read output of 'charconvert'");
2634 }
2635
2636 if (errmsg != NULL)
2637 {
2638 /* Don't use emsg(), it breaks mappings, the retry with
2639 * another type of conversion might still work. */
2640 MSG(errmsg);
2641 if (tmpname != NULL)
2642 {
2643 mch_remove(tmpname); /* delete converted file */
2644 vim_free(tmpname);
2645 tmpname = NULL;
2646 }
2647 }
2648
2649 /* If the input file is closed, open it (caller should check for error). */
2650 if (*fdp < 0)
2651 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2652
2653 return tmpname;
2654}
2655# endif
2656
2657#endif
2658
2659#ifdef FEAT_VIMINFO
2660/*
2661 * Read marks for the current buffer from the viminfo file, when we support
2662 * buffer marks and the buffer has a name.
2663 */
2664 static void
2665check_marks_read()
2666{
2667 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2668 && curbuf->b_ffname != NULL)
2669 read_viminfo(NULL, FALSE, TRUE, FALSE);
2670
2671 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2672 * the ' parameter after opening a buffer. */
2673 curbuf->b_marks_read = TRUE;
2674}
2675#endif
2676
2677#ifdef FEAT_CRYPT
2678/*
2679 * Check for magic number used for encryption.
2680 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2681 * *filesizep are updated.
2682 * Return the (new) encryption key, NULL for no encryption.
2683 */
2684 static char_u *
2685check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
2686 char_u *cryptkey; /* previous encryption key or NULL */
2687 char_u *ptr; /* pointer to read bytes */
2688 long *sizep; /* length of read bytes */
2689 long *filesizep; /* nr of bytes used from file */
2690 int newfile; /* editing a new buffer */
2691{
2692 if (*sizep >= CRYPT_MAGIC_LEN
2693 && STRNCMP(ptr, CRYPT_MAGIC, CRYPT_MAGIC_LEN) == 0)
2694 {
2695 if (cryptkey == NULL)
2696 {
2697 if (*curbuf->b_p_key)
2698 cryptkey = curbuf->b_p_key;
2699 else
2700 {
2701 /* When newfile is TRUE, store the typed key
2702 * in the 'key' option and don't free it. */
2703 cryptkey = get_crypt_key(newfile, FALSE);
2704 /* check if empty key entered */
2705 if (cryptkey != NULL && *cryptkey == NUL)
2706 {
2707 if (cryptkey != curbuf->b_p_key)
2708 vim_free(cryptkey);
2709 cryptkey = NULL;
2710 }
2711 }
2712 }
2713
2714 if (cryptkey != NULL)
2715 {
2716 crypt_init_keys(cryptkey);
2717
2718 /* Remove magic number from the text */
2719 *filesizep += CRYPT_MAGIC_LEN;
2720 *sizep -= CRYPT_MAGIC_LEN;
2721 mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN, (size_t)*sizep);
2722 }
2723 }
2724 /* When starting to edit a new file which does not have
2725 * encryption, clear the 'key' option, except when
2726 * starting up (called with -x argument) */
2727 else if (newfile && *curbuf->b_p_key && !starting)
2728 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2729
2730 return cryptkey;
2731}
2732#endif
2733
2734#ifdef UNIX
2735 static void
2736set_file_time(fname, atime, mtime)
2737 char_u *fname;
2738 time_t atime; /* access time */
2739 time_t mtime; /* modification time */
2740{
2741# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
2742 struct utimbuf buf;
2743
2744 buf.actime = atime;
2745 buf.modtime = mtime;
2746 (void)utime((char *)fname, &buf);
2747# else
2748# if defined(HAVE_UTIMES)
2749 struct timeval tvp[2];
2750
2751 tvp[0].tv_sec = atime;
2752 tvp[0].tv_usec = 0;
2753 tvp[1].tv_sec = mtime;
2754 tvp[1].tv_usec = 0;
2755# ifdef NeXT
2756 (void)utimes((char *)fname, tvp);
2757# else
2758 (void)utimes((char *)fname, (const struct timeval *)&tvp);
2759# endif
2760# endif
2761# endif
2762}
2763#endif /* UNIX */
2764
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002765#if defined(VMS) && !defined(MIN)
2766/* Older DECC compiler for VAX doesn't define MIN() */
2767# define MIN(a, b) ((a) < (b) ? (a) : (b))
2768#endif
2769
Bram Moolenaar071d4272004-06-13 20:20:40 +00002770/*
Bram Moolenaar5386a122007-06-28 20:02:32 +00002771 * Return TRUE if a file appears to be read-only from the file permissions.
2772 */
2773 int
2774check_file_readonly(fname, perm)
2775 char_u *fname; /* full path to file */
2776 int perm; /* known permissions on file */
2777{
2778#ifndef USE_MCH_ACCESS
2779 int fd = 0;
2780#endif
2781
2782 return (
2783#ifdef USE_MCH_ACCESS
2784# ifdef UNIX
2785 (perm & 0222) == 0 ||
2786# endif
2787 mch_access((char *)fname, W_OK)
2788#else
2789 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
2790 ? TRUE : (close(fd), FALSE)
2791#endif
2792 );
2793}
2794
2795
2796/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00002797 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00002798 *
2799 * We do our own buffering here because fwrite() is so slow.
2800 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00002801 * If "forceit" is true, we don't care for errors when attempting backups.
2802 * In case of an error everything possible is done to restore the original
2803 * file. But when "forceit" is TRUE, we risk loosing it.
2804 *
2805 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
2806 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002807 *
2808 * This function must NOT use NameBuff (because it's called by autowrite()).
2809 *
2810 * return FAIL for failure, OK otherwise
2811 */
2812 int
2813buf_write(buf, fname, sfname, start, end, eap, append, forceit,
2814 reset_changed, filtering)
2815 buf_T *buf;
2816 char_u *fname;
2817 char_u *sfname;
2818 linenr_T start, end;
2819 exarg_T *eap; /* for forced 'ff' and 'fenc', can be
2820 NULL! */
Bram Moolenaar292ad192005-12-11 21:29:51 +00002821 int append; /* append to the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002822 int forceit;
2823 int reset_changed;
2824 int filtering;
2825{
2826 int fd;
2827 char_u *backup = NULL;
2828 int backup_copy = FALSE; /* copy the original file? */
2829 int dobackup;
2830 char_u *ffname;
2831 char_u *wfname = NULL; /* name of file to write to */
2832 char_u *s;
2833 char_u *ptr;
2834 char_u c;
2835 int len;
2836 linenr_T lnum;
2837 long nchars;
2838 char_u *errmsg = NULL;
2839 char_u *errnum = NULL;
2840 char_u *buffer;
2841 char_u smallbuf[SMBUFSIZE];
2842 char_u *backup_ext;
2843 int bufsize;
2844 long perm; /* file permissions */
2845 int retval = OK;
2846 int newfile = FALSE; /* TRUE if file doesn't exist yet */
2847 int msg_save = msg_scroll;
2848 int overwriting; /* TRUE if writing over original */
2849 int no_eol = FALSE; /* no end-of-line written */
2850 int device = FALSE; /* writing to a device */
2851 struct stat st_old;
2852 int prev_got_int = got_int;
2853 int file_readonly = FALSE; /* overwritten file is read-only */
2854 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
2855#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
2856 int made_writable = FALSE; /* 'w' bit has been set */
2857#endif
2858 /* writing everything */
2859 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
2860#ifdef FEAT_AUTOCMD
2861 linenr_T old_line_count = buf->b_ml.ml_line_count;
2862#endif
2863 int attr;
2864 int fileformat;
2865 int write_bin;
2866 struct bw_info write_info; /* info for buf_write_bytes() */
2867#ifdef FEAT_MBYTE
2868 int converted = FALSE;
2869 int notconverted = FALSE;
2870 char_u *fenc; /* effective 'fileencoding' */
2871 char_u *fenc_tofree = NULL; /* allocated "fenc" */
2872#endif
2873#ifdef HAS_BW_FLAGS
2874 int wb_flags = 0;
2875#endif
2876#ifdef HAVE_ACL
2877 vim_acl_T acl = NULL; /* ACL copied from original file to
2878 backup or new file */
2879#endif
2880
2881 if (fname == NULL || *fname == NUL) /* safety check */
2882 return FAIL;
2883
2884 /*
2885 * Disallow writing from .exrc and .vimrc in current directory for
2886 * security reasons.
2887 */
2888 if (check_secure())
2889 return FAIL;
2890
2891 /* Avoid a crash for a long name. */
2892 if (STRLEN(fname) >= MAXPATHL)
2893 {
2894 EMSG(_(e_longname));
2895 return FAIL;
2896 }
2897
2898#ifdef FEAT_MBYTE
2899 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
2900 write_info.bw_conv_buf = NULL;
2901 write_info.bw_conv_error = FALSE;
2902 write_info.bw_restlen = 0;
2903# ifdef USE_ICONV
2904 write_info.bw_iconv_fd = (iconv_t)-1;
2905# endif
2906#endif
2907
Bram Moolenaardf177f62005-02-22 08:39:57 +00002908 /* After writing a file changedtick changes but we don't want to display
2909 * the line. */
2910 ex_no_reprint = TRUE;
2911
Bram Moolenaar071d4272004-06-13 20:20:40 +00002912 /*
2913 * If there is no file name yet, use the one for the written file.
2914 * BF_NOTEDITED is set to reflect this (in case the write fails).
2915 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00002916 * Don't do this when appending.
2917 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002919 if (buf->b_ffname == NULL
2920 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921 && whole
2922 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00002923#ifdef FEAT_QUICKFIX
2924 && !bt_nofile(buf)
2925#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00002927 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002928 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
2929 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002930 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002931 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002932 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933 }
2934
2935 if (sfname == NULL)
2936 sfname = fname;
2937 /*
2938 * For Unix: Use the short file name whenever possible.
2939 * Avoids problems with networks and when directory names are changed.
2940 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
2941 * another directory, which we don't detect
2942 */
2943 ffname = fname; /* remember full fname */
2944#ifdef UNIX
2945 fname = sfname;
2946#endif
2947
2948 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
2949 overwriting = TRUE;
2950 else
2951 overwriting = FALSE;
2952
2953 if (exiting)
2954 settmode(TMODE_COOK); /* when exiting allow typahead now */
2955
2956 ++no_wait_return; /* don't wait for return yet */
2957
2958 /*
2959 * Set '[ and '] marks to the lines to be written.
2960 */
2961 buf->b_op_start.lnum = start;
2962 buf->b_op_start.col = 0;
2963 buf->b_op_end.lnum = end;
2964 buf->b_op_end.col = 0;
2965
2966#ifdef FEAT_AUTOCMD
2967 {
2968 aco_save_T aco;
2969 int buf_ffname = FALSE;
2970 int buf_sfname = FALSE;
2971 int buf_fname_f = FALSE;
2972 int buf_fname_s = FALSE;
2973 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002974 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002975 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002976
2977 /*
2978 * Apply PRE aucocommands.
2979 * Set curbuf to the buffer to be written.
2980 * Careful: The autocommands may call buf_write() recursively!
2981 */
2982 if (ffname == buf->b_ffname)
2983 buf_ffname = TRUE;
2984 if (sfname == buf->b_sfname)
2985 buf_sfname = TRUE;
2986 if (fname == buf->b_ffname)
2987 buf_fname_f = TRUE;
2988 if (fname == buf->b_sfname)
2989 buf_fname_s = TRUE;
2990
2991 /* set curwin/curbuf to buf and save a few things */
2992 aucmd_prepbuf(&aco, buf);
2993
2994 if (append)
2995 {
2996 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
2997 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002998 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00002999#ifdef FEAT_QUICKFIX
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003000 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003001 nofile_err = TRUE;
3002 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003003#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003004 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003005 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003006 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003007 }
3008 else if (filtering)
3009 {
3010 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
3011 NULL, sfname, FALSE, curbuf, eap);
3012 }
3013 else if (reset_changed && whole)
3014 {
3015 if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
3016 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003017 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003018#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003019 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003020 nofile_err = TRUE;
3021 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003022#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003023 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003024 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003025 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003026 }
3027 else
3028 {
3029 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
3030 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003031 {
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003032#ifdef FEAT_QUICKFIX
Bram Moolenaar19a09a12005-03-04 23:39:37 +00003033 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003034 nofile_err = TRUE;
3035 else
Bram Moolenaarb1b715d2006-01-21 22:09:43 +00003036#endif
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003037 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003039 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040 }
3041
3042 /* restore curwin/curbuf and a few other things */
3043 aucmd_restbuf(&aco);
3044
3045 /*
3046 * In three situations we return here and don't write the file:
3047 * 1. the autocommands deleted or unloaded the buffer.
3048 * 2. The autocommands abort script processing.
3049 * 3. If one of the "Cmd" autocommands was executed.
3050 */
3051 if (!buf_valid(buf))
3052 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00003053 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar1e015462005-09-25 22:16:38 +00003054 || did_cmd || nofile_err
3055#ifdef FEAT_EVAL
3056 || aborting()
3057#endif
3058 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003059 {
3060 --no_wait_return;
3061 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00003062 if (nofile_err)
3063 EMSG(_("E676: No matching autocommands for acwrite buffer"));
3064
Bram Moolenaar1e015462005-09-25 22:16:38 +00003065 if (nofile_err
3066#ifdef FEAT_EVAL
3067 || aborting()
3068#endif
3069 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003070 /* An aborting error, interrupt or exception in the
3071 * autocommands. */
3072 return FAIL;
3073 if (did_cmd)
3074 {
3075 if (buf == NULL)
3076 /* The buffer was deleted. We assume it was written
3077 * (can't retry anyway). */
3078 return OK;
3079 if (overwriting)
3080 {
3081 /* Assume the buffer was written, update the timestamp. */
3082 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00003083 if (append)
3084 buf->b_flags &= ~BF_NEW;
3085 else
3086 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087 }
Bram Moolenaar292ad192005-12-11 21:29:51 +00003088 if (reset_changed && buf->b_changed && !append
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003089 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003090 /* Buffer still changed, the autocommands didn't work
3091 * properly. */
3092 return FAIL;
3093 return OK;
3094 }
3095#ifdef FEAT_EVAL
3096 if (!aborting())
3097#endif
3098 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
3099 return FAIL;
3100 }
3101
3102 /*
3103 * The autocommands may have changed the number of lines in the file.
3104 * When writing the whole file, adjust the end.
3105 * When writing part of the file, assume that the autocommands only
3106 * changed the number of lines that are to be written (tricky!).
3107 */
3108 if (buf->b_ml.ml_line_count != old_line_count)
3109 {
3110 if (whole) /* write all */
3111 end = buf->b_ml.ml_line_count;
3112 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
3113 end += buf->b_ml.ml_line_count - old_line_count;
3114 else /* less lines */
3115 {
3116 end -= old_line_count - buf->b_ml.ml_line_count;
3117 if (end < start)
3118 {
3119 --no_wait_return;
3120 msg_scroll = msg_save;
3121 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
3122 return FAIL;
3123 }
3124 }
3125 }
3126
3127 /*
3128 * The autocommands may have changed the name of the buffer, which may
3129 * be kept in fname, ffname and sfname.
3130 */
3131 if (buf_ffname)
3132 ffname = buf->b_ffname;
3133 if (buf_sfname)
3134 sfname = buf->b_sfname;
3135 if (buf_fname_f)
3136 fname = buf->b_ffname;
3137 if (buf_fname_s)
3138 fname = buf->b_sfname;
3139 }
3140#endif
3141
3142#ifdef FEAT_NETBEANS_INTG
3143 if (usingNetbeans && isNetbeansBuffer(buf))
3144 {
3145 if (whole)
3146 {
3147 /*
3148 * b_changed can be 0 after an undo, but we still need to write
3149 * the buffer to NetBeans.
3150 */
3151 if (buf->b_changed || isNetbeansModified(buf))
3152 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00003153 --no_wait_return; /* may wait for return now */
3154 msg_scroll = msg_save;
3155 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003156 return retval;
3157 }
3158 else
3159 {
3160 errnum = (char_u *)"E656: ";
3161 errmsg = (char_u *)_("NetBeans dissallows writes of unmodified buffers");
3162 buffer = NULL;
3163 goto fail;
3164 }
3165 }
3166 else
3167 {
3168 errnum = (char_u *)"E657: ";
3169 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
3170 buffer = NULL;
3171 goto fail;
3172 }
3173 }
3174#endif
3175
3176 if (shortmess(SHM_OVER) && !exiting)
3177 msg_scroll = FALSE; /* overwrite previous file message */
3178 else
3179 msg_scroll = TRUE; /* don't overwrite previous file message */
3180 if (!filtering)
3181 filemess(buf,
3182#ifndef UNIX
3183 sfname,
3184#else
3185 fname,
3186#endif
3187 (char_u *)"", 0); /* show that we are busy */
3188 msg_scroll = FALSE; /* always overwrite the file message now */
3189
3190 buffer = alloc(BUFSIZE);
3191 if (buffer == NULL) /* can't allocate big buffer, use small
3192 * one (to be able to write when out of
3193 * memory) */
3194 {
3195 buffer = smallbuf;
3196 bufsize = SMBUFSIZE;
3197 }
3198 else
3199 bufsize = BUFSIZE;
3200
3201 /*
3202 * Get information about original file (if there is one).
3203 */
3204#if defined(UNIX) && !defined(ARCHIE)
3205 st_old.st_dev = st_old.st_ino = 0;
3206 perm = -1;
3207 if (mch_stat((char *)fname, &st_old) < 0)
3208 newfile = TRUE;
3209 else
3210 {
3211 perm = st_old.st_mode;
3212 if (!S_ISREG(st_old.st_mode)) /* not a file */
3213 {
3214 if (S_ISDIR(st_old.st_mode))
3215 {
3216 errnum = (char_u *)"E502: ";
3217 errmsg = (char_u *)_("is a directory");
3218 goto fail;
3219 }
3220 if (mch_nodetype(fname) != NODE_WRITABLE)
3221 {
3222 errnum = (char_u *)"E503: ";
3223 errmsg = (char_u *)_("is not a file or writable device");
3224 goto fail;
3225 }
3226 /* It's a device of some kind (or a fifo) which we can write to
3227 * but for which we can't make a backup. */
3228 device = TRUE;
3229 newfile = TRUE;
3230 perm = -1;
3231 }
3232 }
3233#else /* !UNIX */
3234 /*
3235 * Check for a writable device name.
3236 */
3237 c = mch_nodetype(fname);
3238 if (c == NODE_OTHER)
3239 {
3240 errnum = (char_u *)"E503: ";
3241 errmsg = (char_u *)_("is not a file or writable device");
3242 goto fail;
3243 }
3244 if (c == NODE_WRITABLE)
3245 {
Bram Moolenaar043545e2006-10-10 16:44:07 +00003246# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
3247 /* MS-Windows allows opening a device, but we will probably get stuck
3248 * trying to write to it. */
3249 if (!p_odev)
3250 {
3251 errnum = (char_u *)"E796: ";
3252 errmsg = (char_u *)_("writing to device disabled with 'opendevice' option");
3253 goto fail;
3254 }
3255# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003256 device = TRUE;
3257 newfile = TRUE;
3258 perm = -1;
3259 }
3260 else
3261 {
3262 perm = mch_getperm(fname);
3263 if (perm < 0)
3264 newfile = TRUE;
3265 else if (mch_isdir(fname))
3266 {
3267 errnum = (char_u *)"E502: ";
3268 errmsg = (char_u *)_("is a directory");
3269 goto fail;
3270 }
3271 if (overwriting)
3272 (void)mch_stat((char *)fname, &st_old);
3273 }
3274#endif /* !UNIX */
3275
3276 if (!device && !newfile)
3277 {
3278 /*
3279 * Check if the file is really writable (when renaming the file to
3280 * make a backup we won't discover it later).
3281 */
Bram Moolenaar5386a122007-06-28 20:02:32 +00003282 file_readonly = check_file_readonly(fname, (int)perm);
3283
Bram Moolenaar071d4272004-06-13 20:20:40 +00003284 if (!forceit && file_readonly)
3285 {
3286 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3287 {
3288 errnum = (char_u *)"E504: ";
3289 errmsg = (char_u *)_(err_readonly);
3290 }
3291 else
3292 {
3293 errnum = (char_u *)"E505: ";
3294 errmsg = (char_u *)_("is read-only (add ! to override)");
3295 }
3296 goto fail;
3297 }
3298
3299 /*
3300 * Check if the timestamp hasn't changed since reading the file.
3301 */
3302 if (overwriting)
3303 {
3304 retval = check_mtime(buf, &st_old);
3305 if (retval == FAIL)
3306 goto fail;
3307 }
3308 }
3309
3310#ifdef HAVE_ACL
3311 /*
3312 * For systems that support ACL: get the ACL from the original file.
3313 */
3314 if (!newfile)
3315 acl = mch_get_acl(fname);
3316#endif
3317
3318 /*
3319 * If 'backupskip' is not empty, don't make a backup for some files.
3320 */
3321 dobackup = (p_wb || p_bk || *p_pm != NUL);
3322#ifdef FEAT_WILDIGN
3323 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3324 dobackup = FALSE;
3325#endif
3326
3327 /*
3328 * Save the value of got_int and reset it. We don't want a previous
3329 * interruption cancel writing, only hitting CTRL-C while writing should
3330 * abort it.
3331 */
3332 prev_got_int = got_int;
3333 got_int = FALSE;
3334
3335 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3336 buf->b_saving = TRUE;
3337
3338 /*
3339 * If we are not appending or filtering, the file exists, and the
3340 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3341 * When 'patchmode' is set also make a backup when appending.
3342 *
3343 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3344 * off. This helps when editing large files on almost-full disks.
3345 */
3346 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3347 {
3348#if defined(UNIX) || defined(WIN32)
3349 struct stat st;
3350#endif
3351
3352 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3353 backup_copy = TRUE;
3354#if defined(UNIX) || defined(WIN32)
3355 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3356 {
3357 int i;
3358
3359# ifdef UNIX
3360 /*
3361 * Don't rename the file when:
3362 * - it's a hard link
3363 * - it's a symbolic link
3364 * - we don't have write permission in the directory
3365 * - we can't set the owner/group of the new file
3366 */
3367 if (st_old.st_nlink > 1
3368 || mch_lstat((char *)fname, &st) < 0
3369 || st.st_dev != st_old.st_dev
Bram Moolenaara5792f52005-11-23 21:25:05 +00003370 || st.st_ino != st_old.st_ino
3371# ifndef HAVE_FCHOWN
3372 || st.st_uid != st_old.st_uid
3373 || st.st_gid != st_old.st_gid
3374# endif
3375 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 backup_copy = TRUE;
3377 else
Bram Moolenaar03f48552006-02-28 23:52:23 +00003378# else
3379# ifdef WIN32
3380 /* On NTFS file systems hard links are possible. */
3381 if (mch_is_linked(fname))
3382 backup_copy = TRUE;
3383 else
3384# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003385# endif
3386 {
3387 /*
3388 * Check if we can create a file and set the owner/group to
3389 * the ones from the original file.
3390 * First find a file name that doesn't exist yet (use some
3391 * arbitrary numbers).
3392 */
3393 STRCPY(IObuff, fname);
3394 for (i = 4913; ; i += 123)
3395 {
3396 sprintf((char *)gettail(IObuff), "%d", i);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003397 if (mch_lstat((char *)IObuff, &st) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003398 break;
3399 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00003400 fd = mch_open((char *)IObuff,
3401 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003402 if (fd < 0) /* can't write in directory */
3403 backup_copy = TRUE;
3404 else
3405 {
3406# ifdef UNIX
Bram Moolenaara5792f52005-11-23 21:25:05 +00003407# ifdef HAVE_FCHOWN
3408 fchown(fd, st_old.st_uid, st_old.st_gid);
3409# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003410 if (mch_stat((char *)IObuff, &st) < 0
3411 || st.st_uid != st_old.st_uid
3412 || st.st_gid != st_old.st_gid
3413 || st.st_mode != perm)
3414 backup_copy = TRUE;
3415# endif
Bram Moolenaar98358622005-11-28 22:58:23 +00003416 /* Close the file before removing it, on MS-Windows we
3417 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003418 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003419 mch_remove(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003420 }
3421 }
3422 }
3423
3424# ifdef UNIX
3425 /*
3426 * Break symlinks and/or hardlinks if we've been asked to.
3427 */
3428 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3429 {
3430 int lstat_res;
3431
3432 lstat_res = mch_lstat((char *)fname, &st);
3433
3434 /* Symlinks. */
3435 if ((bkc_flags & BKC_BREAKSYMLINK)
3436 && lstat_res == 0
3437 && st.st_ino != st_old.st_ino)
3438 backup_copy = FALSE;
3439
3440 /* Hardlinks. */
3441 if ((bkc_flags & BKC_BREAKHARDLINK)
3442 && st_old.st_nlink > 1
3443 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3444 backup_copy = FALSE;
3445 }
3446#endif
3447
3448#endif
3449
3450 /* make sure we have a valid backup extension to use */
3451 if (*p_bex == NUL)
3452 {
3453#ifdef RISCOS
3454 backup_ext = (char_u *)"/bak";
3455#else
3456 backup_ext = (char_u *)".bak";
3457#endif
3458 }
3459 else
3460 backup_ext = p_bex;
3461
3462 if (backup_copy
3463 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3464 {
3465 int bfd;
3466 char_u *copybuf, *wp;
3467 int some_error = FALSE;
3468 struct stat st_new;
3469 char_u *dirp;
3470 char_u *rootname;
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003471#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003472 int did_set_shortname;
3473#endif
3474
3475 copybuf = alloc(BUFSIZE + 1);
3476 if (copybuf == NULL)
3477 {
3478 some_error = TRUE; /* out of memory */
3479 goto nobackup;
3480 }
3481
3482 /*
3483 * Try to make the backup in each directory in the 'bdir' option.
3484 *
3485 * Unix semantics has it, that we may have a writable file,
3486 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3487 * - the directory is not writable,
3488 * - the file may be a symbolic link,
3489 * - the file may belong to another user/group, etc.
3490 *
3491 * For these reasons, the existing writable file must be truncated
3492 * and reused. Creation of a backup COPY will be attempted.
3493 */
3494 dirp = p_bdir;
3495 while (*dirp)
3496 {
3497#ifdef UNIX
3498 st_new.st_ino = 0;
3499 st_new.st_dev = 0;
3500 st_new.st_gid = 0;
3501#endif
3502
3503 /*
3504 * Isolate one directory name, using an entry in 'bdir'.
3505 */
3506 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3507 rootname = get_file_in_dir(fname, copybuf);
3508 if (rootname == NULL)
3509 {
3510 some_error = TRUE; /* out of memory */
3511 goto nobackup;
3512 }
3513
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003514#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003515 did_set_shortname = FALSE;
3516#endif
3517
3518 /*
3519 * May try twice if 'shortname' not set.
3520 */
3521 for (;;)
3522 {
3523 /*
3524 * Make backup file name.
3525 */
3526 backup = buf_modname(
3527#ifdef SHORT_FNAME
3528 TRUE,
3529#else
3530 (buf->b_p_sn || buf->b_shortname),
3531#endif
3532 rootname, backup_ext, FALSE);
3533 if (backup == NULL)
3534 {
3535 vim_free(rootname);
3536 some_error = TRUE; /* out of memory */
3537 goto nobackup;
3538 }
3539
3540 /*
3541 * Check if backup file already exists.
3542 */
3543 if (mch_stat((char *)backup, &st_new) >= 0)
3544 {
3545#ifdef UNIX
3546 /*
3547 * Check if backup file is same as original file.
3548 * May happen when modname() gave the same file back.
3549 * E.g. silly link, or file name-length reached.
3550 * If we don't check here, we either ruin the file
3551 * when copying or erase it after writing. jw.
3552 */
3553 if (st_new.st_dev == st_old.st_dev
3554 && st_new.st_ino == st_old.st_ino)
3555 {
3556 vim_free(backup);
3557 backup = NULL; /* no backup file to delete */
3558# ifndef SHORT_FNAME
3559 /*
3560 * may try again with 'shortname' set
3561 */
3562 if (!(buf->b_shortname || buf->b_p_sn))
3563 {
3564 buf->b_shortname = TRUE;
3565 did_set_shortname = TRUE;
3566 continue;
3567 }
3568 /* setting shortname didn't help */
3569 if (did_set_shortname)
3570 buf->b_shortname = FALSE;
3571# endif
3572 break;
3573 }
3574#endif
3575
3576 /*
3577 * If we are not going to keep the backup file, don't
3578 * delete an existing one, try to use another name.
3579 * Change one character, just before the extension.
3580 */
3581 if (!p_bk)
3582 {
3583 wp = backup + STRLEN(backup) - 1
3584 - STRLEN(backup_ext);
3585 if (wp < backup) /* empty file name ??? */
3586 wp = backup;
3587 *wp = 'z';
3588 while (*wp > 'a'
3589 && mch_stat((char *)backup, &st_new) >= 0)
3590 --*wp;
3591 /* They all exist??? Must be something wrong. */
3592 if (*wp == 'a')
3593 {
3594 vim_free(backup);
3595 backup = NULL;
3596 }
3597 }
3598 }
3599 break;
3600 }
3601 vim_free(rootname);
3602
3603 /*
3604 * Try to create the backup file
3605 */
3606 if (backup != NULL)
3607 {
3608 /* remove old backup, if present */
3609 mch_remove(backup);
3610 /* Open with O_EXCL to avoid the file being created while
3611 * we were sleeping (symlink hacker attack?) */
3612 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00003613 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
3614 perm & 0777);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003615 if (bfd < 0)
3616 {
3617 vim_free(backup);
3618 backup = NULL;
3619 }
3620 else
3621 {
3622 /* set file protection same as original file, but
3623 * strip s-bit */
3624 (void)mch_setperm(backup, perm & 0777);
3625
3626#ifdef UNIX
3627 /*
3628 * Try to set the group of the backup same as the
3629 * original file. If this fails, set the protection
3630 * bits for the group same as the protection bits for
3631 * others.
3632 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003633 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00003634# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003635 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003636# endif
3637 )
3638 mch_setperm(backup,
3639 (perm & 0707) | ((perm & 07) << 3));
3640#endif
3641
3642 /*
3643 * copy the file.
3644 */
3645 write_info.bw_fd = bfd;
3646 write_info.bw_buf = copybuf;
3647#ifdef HAS_BW_FLAGS
3648 write_info.bw_flags = FIO_NOCONVERT;
3649#endif
3650 while ((write_info.bw_len = vim_read(fd, copybuf,
3651 BUFSIZE)) > 0)
3652 {
3653 if (buf_write_bytes(&write_info) == FAIL)
3654 {
3655 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3656 break;
3657 }
3658 ui_breakcheck();
3659 if (got_int)
3660 {
3661 errmsg = (char_u *)_(e_interr);
3662 break;
3663 }
3664 }
3665
3666 if (close(bfd) < 0 && errmsg == NULL)
3667 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3668 if (write_info.bw_len < 0)
3669 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3670#ifdef UNIX
3671 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3672#endif
3673#ifdef HAVE_ACL
3674 mch_set_acl(backup, acl);
3675#endif
3676 break;
3677 }
3678 }
3679 }
3680 nobackup:
3681 close(fd); /* ignore errors for closing read file */
3682 vim_free(copybuf);
3683
3684 if (backup == NULL && errmsg == NULL)
3685 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3686 /* ignore errors when forceit is TRUE */
3687 if ((some_error || errmsg != NULL) && !forceit)
3688 {
3689 retval = FAIL;
3690 goto fail;
3691 }
3692 errmsg = NULL;
3693 }
3694 else
3695 {
3696 char_u *dirp;
3697 char_u *p;
3698 char_u *rootname;
3699
3700 /*
3701 * Make a backup by renaming the original file.
3702 */
3703 /*
3704 * If 'cpoptions' includes the "W" flag, we don't want to
3705 * overwrite a read-only file. But rename may be possible
3706 * anyway, thus we need an extra check here.
3707 */
3708 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3709 {
3710 errnum = (char_u *)"E504: ";
3711 errmsg = (char_u *)_(err_readonly);
3712 goto fail;
3713 }
3714
3715 /*
3716 *
3717 * Form the backup file name - change path/fo.o.h to
3718 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3719 * that works is used.
3720 */
3721 dirp = p_bdir;
3722 while (*dirp)
3723 {
3724 /*
3725 * Isolate one directory name and make the backup file name.
3726 */
3727 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3728 rootname = get_file_in_dir(fname, IObuff);
3729 if (rootname == NULL)
3730 backup = NULL;
3731 else
3732 {
3733 backup = buf_modname(
3734#ifdef SHORT_FNAME
3735 TRUE,
3736#else
3737 (buf->b_p_sn || buf->b_shortname),
3738#endif
3739 rootname, backup_ext, FALSE);
3740 vim_free(rootname);
3741 }
3742
3743 if (backup != NULL)
3744 {
3745 /*
3746 * If we are not going to keep the backup file, don't
3747 * delete an existing one, try to use another name.
3748 * Change one character, just before the extension.
3749 */
3750 if (!p_bk && mch_getperm(backup) >= 0)
3751 {
3752 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3753 if (p < backup) /* empty file name ??? */
3754 p = backup;
3755 *p = 'z';
3756 while (*p > 'a' && mch_getperm(backup) >= 0)
3757 --*p;
3758 /* They all exist??? Must be something wrong! */
3759 if (*p == 'a')
3760 {
3761 vim_free(backup);
3762 backup = NULL;
3763 }
3764 }
3765 }
3766 if (backup != NULL)
3767 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003768 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00003769 * Delete any existing backup and move the current version
3770 * to the backup. For safety, we don't remove the backup
3771 * until the write has finished successfully. And if the
3772 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 */
3774 /*
3775 * If the renaming of the original file to the backup file
3776 * works, quit here.
3777 */
3778 if (vim_rename(fname, backup) == 0)
3779 break;
3780
3781 vim_free(backup); /* don't do the rename below */
3782 backup = NULL;
3783 }
3784 }
3785 if (backup == NULL && !forceit)
3786 {
3787 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3788 goto fail;
3789 }
3790 }
3791 }
3792
3793#if defined(UNIX) && !defined(ARCHIE)
3794 /* When using ":w!" and the file was read-only: make it writable */
3795 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3796 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3797 {
3798 perm |= 0200;
3799 (void)mch_setperm(fname, perm);
3800 made_writable = TRUE;
3801 }
3802#endif
3803
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003804 /* When using ":w!" and writing to the current file, 'readonly' makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003805 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
3806 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003807 {
3808 buf->b_p_ro = FALSE;
3809#ifdef FEAT_TITLE
3810 need_maketitle = TRUE; /* set window title later */
3811#endif
3812#ifdef FEAT_WINDOWS
3813 status_redraw_all(); /* redraw status lines later */
3814#endif
3815 }
3816
3817 if (end > buf->b_ml.ml_line_count)
3818 end = buf->b_ml.ml_line_count;
3819 if (buf->b_ml.ml_flags & ML_EMPTY)
3820 start = end + 1;
3821
3822 /*
3823 * If the original file is being overwritten, there is a small chance that
3824 * we crash in the middle of writing. Therefore the file is preserved now.
3825 * This makes all block numbers positive so that recovery does not need
3826 * the original file.
3827 * Don't do this if there is a backup file and we are exiting.
3828 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003829 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00003830 && !(exiting && backup != NULL))
3831 {
3832 ml_preserve(buf, FALSE);
3833 if (got_int)
3834 {
3835 errmsg = (char_u *)_(e_interr);
3836 goto restore_backup;
3837 }
3838 }
3839
3840#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
3841 /*
3842 * Before risking to lose the original file verify if there's
3843 * a resource fork to preserve, and if cannot be done warn
3844 * the users. This happens when overwriting without backups.
3845 */
3846 if (backup == NULL && overwriting && !append)
3847 if (mch_has_resource_fork(fname))
3848 {
3849 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
3850 goto restore_backup;
3851 }
3852#endif
3853
3854#ifdef VMS
3855 vms_remove_version(fname); /* remove version */
3856#endif
3857 /* Default: write the the file directly. May write to a temp file for
3858 * multi-byte conversion. */
3859 wfname = fname;
3860
3861#ifdef FEAT_MBYTE
3862 /* Check for forced 'fileencoding' from "++opt=val" argument. */
3863 if (eap != NULL && eap->force_enc != 0)
3864 {
3865 fenc = eap->cmd + eap->force_enc;
3866 fenc = enc_canonize(fenc);
3867 fenc_tofree = fenc;
3868 }
3869 else
3870 fenc = buf->b_p_fenc;
3871
3872 /*
3873 * The file needs to be converted when 'fileencoding' is set and
3874 * 'fileencoding' differs from 'encoding'.
3875 */
3876 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
3877
3878 /*
3879 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3880 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3881 * Prepare the flags for it and allocate bw_conv_buf when needed.
3882 */
3883 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
3884 {
3885 wb_flags = get_fio_flags(fenc);
3886 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
3887 {
3888 /* Need to allocate a buffer to translate into. */
3889 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
3890 write_info.bw_conv_buflen = bufsize * 2;
3891 else /* FIO_UCS4 */
3892 write_info.bw_conv_buflen = bufsize * 4;
3893 write_info.bw_conv_buf
3894 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3895 if (write_info.bw_conv_buf == NULL)
3896 end = 0;
3897 }
3898 }
3899
3900# ifdef WIN3264
3901 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
3902 {
3903 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
3904 write_info.bw_conv_buflen = bufsize * 4;
3905 write_info.bw_conv_buf
3906 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3907 if (write_info.bw_conv_buf == NULL)
3908 end = 0;
3909 }
3910# endif
3911
3912# ifdef MACOS_X
3913 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
3914 {
3915 write_info.bw_conv_buflen = bufsize * 3;
3916 write_info.bw_conv_buf
3917 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3918 if (write_info.bw_conv_buf == NULL)
3919 end = 0;
3920 }
3921# endif
3922
3923# if defined(FEAT_EVAL) || defined(USE_ICONV)
3924 if (converted && wb_flags == 0)
3925 {
3926# ifdef USE_ICONV
3927 /*
3928 * Use iconv() conversion when conversion is needed and it's not done
3929 * internally.
3930 */
3931 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3932 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3933 if (write_info.bw_iconv_fd != (iconv_t)-1)
3934 {
3935 /* We're going to use iconv(), allocate a buffer to convert in. */
3936 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3937 write_info.bw_conv_buf
3938 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3939 if (write_info.bw_conv_buf == NULL)
3940 end = 0;
3941 write_info.bw_first = TRUE;
3942 }
3943# ifdef FEAT_EVAL
3944 else
3945# endif
3946# endif
3947
3948# ifdef FEAT_EVAL
3949 /*
3950 * When the file needs to be converted with 'charconvert' after
3951 * writing, write to a temp file instead and let the conversion
3952 * overwrite the original file.
3953 */
3954 if (*p_ccv != NUL)
3955 {
3956 wfname = vim_tempname('w');
3957 if (wfname == NULL) /* Can't write without a tempfile! */
3958 {
3959 errmsg = (char_u *)_("E214: Can't find temp file for writing");
3960 goto restore_backup;
3961 }
3962 }
3963# endif
3964 }
3965# endif
3966 if (converted && wb_flags == 0
3967# ifdef USE_ICONV
3968 && write_info.bw_iconv_fd == (iconv_t)-1
3969# endif
3970# ifdef FEAT_EVAL
3971 && wfname == fname
3972# endif
3973 )
3974 {
3975 if (!forceit)
3976 {
3977 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
3978 goto restore_backup;
3979 }
3980 notconverted = TRUE;
3981 }
3982#endif
3983
3984 /*
3985 * Open the file "wfname" for writing.
3986 * We may try to open the file twice: If we can't write to the
3987 * file and forceit is TRUE we delete the existing file and try to create
3988 * a new one. If this still fails we may have lost the original file!
3989 * (this may happen when the user reached his quotum for number of files).
3990 * Appending will fail if the file does not exist and forceit is FALSE.
3991 */
3992 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
3993 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3994 : (O_CREAT | O_TRUNC))
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00003995 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003996 {
3997 /*
3998 * A forced write will try to create a new file if the old one is
3999 * still readonly. This may also happen when the directory is
4000 * read-only. In that case the mch_remove() will fail.
4001 */
4002 if (errmsg == NULL)
4003 {
4004#ifdef UNIX
4005 struct stat st;
4006
4007 /* Don't delete the file when it's a hard or symbolic link. */
4008 if ((!newfile && st_old.st_nlink > 1)
4009 || (mch_lstat((char *)fname, &st) == 0
4010 && (st.st_dev != st_old.st_dev
4011 || st.st_ino != st_old.st_ino)))
4012 errmsg = (char_u *)_("E166: Can't open linked file for writing");
4013 else
4014#endif
4015 {
4016 errmsg = (char_u *)_("E212: Can't open file for writing");
4017 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
4018 && perm >= 0)
4019 {
4020#ifdef UNIX
4021 /* we write to the file, thus it should be marked
4022 writable after all */
4023 if (!(perm & 0200))
4024 made_writable = TRUE;
4025 perm |= 0200;
4026 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
4027 perm &= 0777;
4028#endif
4029 if (!append) /* don't remove when appending */
4030 mch_remove(wfname);
4031 continue;
4032 }
4033 }
4034 }
4035
4036restore_backup:
4037 {
4038 struct stat st;
4039
4040 /*
4041 * If we failed to open the file, we don't need a backup. Throw it
4042 * away. If we moved or removed the original file try to put the
4043 * backup in its place.
4044 */
4045 if (backup != NULL && wfname == fname)
4046 {
4047 if (backup_copy)
4048 {
4049 /*
4050 * There is a small chance that we removed the original,
4051 * try to move the copy in its place.
4052 * This may not work if the vim_rename() fails.
4053 * In that case we leave the copy around.
4054 */
4055 /* If file does not exist, put the copy in its place */
4056 if (mch_stat((char *)fname, &st) < 0)
4057 vim_rename(backup, fname);
4058 /* if original file does exist throw away the copy */
4059 if (mch_stat((char *)fname, &st) >= 0)
4060 mch_remove(backup);
4061 }
4062 else
4063 {
4064 /* try to put the original file back */
4065 vim_rename(backup, fname);
4066 }
4067 }
4068
4069 /* if original file no longer exists give an extra warning */
4070 if (!newfile && mch_stat((char *)fname, &st) < 0)
4071 end = 0;
4072 }
4073
4074#ifdef FEAT_MBYTE
4075 if (wfname != fname)
4076 vim_free(wfname);
4077#endif
4078 goto fail;
4079 }
4080 errmsg = NULL;
4081
4082#if defined(MACOS_CLASSIC) || defined(WIN3264)
4083 /* TODO: Is it need for MACOS_X? (Dany) */
4084 /*
4085 * On macintosh copy the original files attributes (i.e. the backup)
Bram Moolenaar7263a772007-05-10 17:35:54 +00004086 * This is done in order to preserve the resource fork and the
4087 * Finder attribute (label, comments, custom icons, file creator)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004088 */
4089 if (backup != NULL && overwriting && !append)
4090 {
4091 if (backup_copy)
4092 (void)mch_copy_file_attribute(wfname, backup);
4093 else
4094 (void)mch_copy_file_attribute(backup, wfname);
4095 }
4096
4097 if (!overwriting && !append)
4098 {
4099 if (buf->b_ffname != NULL)
4100 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
Bram Moolenaar7263a772007-05-10 17:35:54 +00004101 /* Should copy resource fork */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004102 }
4103#endif
4104
4105 write_info.bw_fd = fd;
4106
4107#ifdef FEAT_CRYPT
4108 if (*buf->b_p_key && !filtering)
4109 {
4110 crypt_init_keys(buf->b_p_key);
4111 /* Write magic number, so that Vim knows that this file is encrypted
4112 * when reading it again. This also undergoes utf-8 to ucs-2/4
4113 * conversion when needed. */
4114 write_info.bw_buf = (char_u *)CRYPT_MAGIC;
4115 write_info.bw_len = CRYPT_MAGIC_LEN;
4116 write_info.bw_flags = FIO_NOCONVERT;
4117 if (buf_write_bytes(&write_info) == FAIL)
4118 end = 0;
4119 wb_flags |= FIO_ENCRYPTED;
4120 }
4121#endif
4122
4123 write_info.bw_buf = buffer;
4124 nchars = 0;
4125
4126 /* use "++bin", "++nobin" or 'binary' */
4127 if (eap != NULL && eap->force_bin != 0)
4128 write_bin = (eap->force_bin == FORCE_BIN);
4129 else
4130 write_bin = buf->b_p_bin;
4131
4132#ifdef FEAT_MBYTE
4133 /*
4134 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004135 * Skip it when appending and the file already existed, the BOM only makes
4136 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004137 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004138 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004139 {
4140 write_info.bw_len = make_bom(buffer, fenc);
4141 if (write_info.bw_len > 0)
4142 {
4143 /* don't convert, do encryption */
4144 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4145 if (buf_write_bytes(&write_info) == FAIL)
4146 end = 0;
4147 else
4148 nchars += write_info.bw_len;
4149 }
4150 }
4151#endif
4152
4153 write_info.bw_len = bufsize;
4154#ifdef HAS_BW_FLAGS
4155 write_info.bw_flags = wb_flags;
4156#endif
4157 fileformat = get_fileformat_force(buf, eap);
4158 s = buffer;
4159 len = 0;
4160 for (lnum = start; lnum <= end; ++lnum)
4161 {
4162 /*
4163 * The next while loop is done once for each character written.
4164 * Keep it fast!
4165 */
4166 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
4167 while ((c = *++ptr) != NUL)
4168 {
4169 if (c == NL)
4170 *s = NUL; /* replace newlines with NULs */
4171 else if (c == CAR && fileformat == EOL_MAC)
4172 *s = NL; /* Mac: replace CRs with NLs */
4173 else
4174 *s = c;
4175 ++s;
4176 if (++len != bufsize)
4177 continue;
4178 if (buf_write_bytes(&write_info) == FAIL)
4179 {
4180 end = 0; /* write error: break loop */
4181 break;
4182 }
4183 nchars += bufsize;
4184 s = buffer;
4185 len = 0;
4186 }
4187 /* write failed or last line has no EOL: stop here */
4188 if (end == 0
4189 || (lnum == end
4190 && write_bin
4191 && (lnum == write_no_eol_lnum
4192 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
4193 {
4194 ++lnum; /* written the line, count it */
4195 no_eol = TRUE;
4196 break;
4197 }
4198 if (fileformat == EOL_UNIX)
4199 *s++ = NL;
4200 else
4201 {
4202 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4203 if (fileformat == EOL_DOS) /* write CR-NL */
4204 {
4205 if (++len == bufsize)
4206 {
4207 if (buf_write_bytes(&write_info) == FAIL)
4208 {
4209 end = 0; /* write error: break loop */
4210 break;
4211 }
4212 nchars += bufsize;
4213 s = buffer;
4214 len = 0;
4215 }
4216 *s++ = NL;
4217 }
4218 }
4219 if (++len == bufsize && end)
4220 {
4221 if (buf_write_bytes(&write_info) == FAIL)
4222 {
4223 end = 0; /* write error: break loop */
4224 break;
4225 }
4226 nchars += bufsize;
4227 s = buffer;
4228 len = 0;
4229
4230 ui_breakcheck();
4231 if (got_int)
4232 {
4233 end = 0; /* Interrupted, break loop */
4234 break;
4235 }
4236 }
4237#ifdef VMS
4238 /*
4239 * On VMS there is a problem: newlines get added when writing blocks
4240 * at a time. Fix it by writing a line at a time.
4241 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004242 * Explanation: VAX/DECC RTL insists that records in some RMS
4243 * structures end with a newline (carriage return) character, and if
4244 * they don't it adds one.
4245 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004246 */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004247 if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004248 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004249 int b2write;
4250
4251 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4252 ? MIN(4096, bufsize)
4253 : MIN(buf->b_fab_mrs, bufsize));
4254
4255 b2write = len;
4256 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004257 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004258 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4259 if (buf_write_bytes(&write_info) == FAIL)
4260 {
4261 end = 0;
4262 break;
4263 }
4264 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004265 }
4266 write_info.bw_len = bufsize;
4267 nchars += len;
4268 s = buffer;
4269 len = 0;
4270 }
4271#endif
4272 }
4273 if (len > 0 && end > 0)
4274 {
4275 write_info.bw_len = len;
4276 if (buf_write_bytes(&write_info) == FAIL)
4277 end = 0; /* write error */
4278 nchars += len;
4279 }
4280
4281#if defined(UNIX) && defined(HAVE_FSYNC)
4282 /* On many journalling file systems there is a bug that causes both the
4283 * original and the backup file to be lost when halting the system right
4284 * after writing the file. That's because only the meta-data is
4285 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004286 * been written to disk and we don't lose it.
4287 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004288 * (could be a pipe).
4289 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
4290 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 {
4292 errmsg = (char_u *)_("E667: Fsync failed");
4293 end = 0;
4294 }
4295#endif
4296
Bram Moolenaara5792f52005-11-23 21:25:05 +00004297#ifdef UNIX
4298 /* When creating a new file, set its owner/group to that of the original
4299 * file. Get the new device and inode number. */
4300 if (backup != NULL && !backup_copy)
4301 {
4302# ifdef HAVE_FCHOWN
4303 struct stat st;
4304
4305 /* don't change the owner when it's already OK, some systems remove
4306 * permission or ACL stuff */
4307 if (mch_stat((char *)wfname, &st) < 0
4308 || st.st_uid != st_old.st_uid
4309 || st.st_gid != st_old.st_gid)
4310 {
4311 fchown(fd, st_old.st_uid, st_old.st_gid);
4312 if (perm >= 0) /* set permission again, may have changed */
4313 (void)mch_setperm(wfname, perm);
4314 }
4315# endif
4316 buf_setino(buf);
4317 }
Bram Moolenaar8fa04452005-12-23 22:13:51 +00004318 else if (buf->b_dev < 0)
4319 /* Set the inode when creating a new file. */
4320 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004321#endif
4322
Bram Moolenaar071d4272004-06-13 20:20:40 +00004323 if (close(fd) != 0)
4324 {
4325 errmsg = (char_u *)_("E512: Close failed");
4326 end = 0;
4327 }
4328
4329#ifdef UNIX
4330 if (made_writable)
4331 perm &= ~0200; /* reset 'w' bit for security reasons */
4332#endif
4333 if (perm >= 0) /* set perm. of new file same as old file */
4334 (void)mch_setperm(wfname, perm);
4335#ifdef RISCOS
4336 if (!append && !filtering)
4337 /* Set the filetype after writing the file. */
4338 mch_set_filetype(wfname, buf->b_p_oft);
4339#endif
4340#ifdef HAVE_ACL
4341 /* Probably need to set the ACL before changing the user (can't set the
4342 * ACL on a file the user doesn't own). */
4343 if (!backup_copy)
4344 mch_set_acl(wfname, acl);
4345#endif
4346
Bram Moolenaar071d4272004-06-13 20:20:40 +00004347
4348#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4349 if (wfname != fname)
4350 {
4351 /*
4352 * The file was written to a temp file, now it needs to be converted
4353 * with 'charconvert' to (overwrite) the output file.
4354 */
4355 if (end != 0)
4356 {
4357 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4358 wfname, fname) == FAIL)
4359 {
4360 write_info.bw_conv_error = TRUE;
4361 end = 0;
4362 }
4363 }
4364 mch_remove(wfname);
4365 vim_free(wfname);
4366 }
4367#endif
4368
4369 if (end == 0)
4370 {
4371 if (errmsg == NULL)
4372 {
4373#ifdef FEAT_MBYTE
4374 if (write_info.bw_conv_error)
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00004375 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376 else
4377#endif
4378 if (got_int)
4379 errmsg = (char_u *)_(e_interr);
4380 else
4381 errmsg = (char_u *)_("E514: write error (file system full?)");
4382 }
4383
4384 /*
4385 * If we have a backup file, try to put it in place of the new file,
4386 * because the new file is probably corrupt. This avoids loosing the
4387 * original file when trying to make a backup when writing the file a
4388 * second time.
4389 * When "backup_copy" is set we need to copy the backup over the new
4390 * file. Otherwise rename the backup file.
4391 * If this is OK, don't give the extra warning message.
4392 */
4393 if (backup != NULL)
4394 {
4395 if (backup_copy)
4396 {
4397 /* This may take a while, if we were interrupted let the user
4398 * know we got the message. */
4399 if (got_int)
4400 {
4401 MSG(_(e_interr));
4402 out_flush();
4403 }
4404 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4405 {
4406 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004407 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4408 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004409 {
4410 /* copy the file. */
4411 write_info.bw_buf = smallbuf;
4412#ifdef HAS_BW_FLAGS
4413 write_info.bw_flags = FIO_NOCONVERT;
4414#endif
4415 while ((write_info.bw_len = vim_read(fd, smallbuf,
4416 SMBUFSIZE)) > 0)
4417 if (buf_write_bytes(&write_info) == FAIL)
4418 break;
4419
4420 if (close(write_info.bw_fd) >= 0
4421 && write_info.bw_len == 0)
4422 end = 1; /* success */
4423 }
4424 close(fd); /* ignore errors for closing read file */
4425 }
4426 }
4427 else
4428 {
4429 if (vim_rename(backup, fname) == 0)
4430 end = 1;
4431 }
4432 }
4433 goto fail;
4434 }
4435
4436 lnum -= start; /* compute number of written lines */
4437 --no_wait_return; /* may wait for return now */
4438
4439#if !(defined(UNIX) || defined(VMS))
4440 fname = sfname; /* use shortname now, for the messages */
4441#endif
4442 if (!filtering)
4443 {
4444 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4445 c = FALSE;
4446#ifdef FEAT_MBYTE
4447 if (write_info.bw_conv_error)
4448 {
4449 STRCAT(IObuff, _(" CONVERSION ERROR"));
4450 c = TRUE;
4451 }
4452 else if (notconverted)
4453 {
4454 STRCAT(IObuff, _("[NOT converted]"));
4455 c = TRUE;
4456 }
4457 else if (converted)
4458 {
4459 STRCAT(IObuff, _("[converted]"));
4460 c = TRUE;
4461 }
4462#endif
4463 if (device)
4464 {
4465 STRCAT(IObuff, _("[Device]"));
4466 c = TRUE;
4467 }
4468 else if (newfile)
4469 {
4470 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4471 c = TRUE;
4472 }
4473 if (no_eol)
4474 {
4475 msg_add_eol();
4476 c = TRUE;
4477 }
4478 /* may add [unix/dos/mac] */
4479 if (msg_add_fileformat(fileformat))
4480 c = TRUE;
4481#ifdef FEAT_CRYPT
4482 if (wb_flags & FIO_ENCRYPTED)
4483 {
4484 STRCAT(IObuff, _("[crypted]"));
4485 c = TRUE;
4486 }
4487#endif
4488 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4489 if (!shortmess(SHM_WRITE))
4490 {
4491 if (append)
4492 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4493 else
4494 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4495 }
4496
Bram Moolenaar8f7fd652006-02-21 22:04:51 +00004497 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004498 }
4499
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004500 /* When written everything correctly: reset 'modified'. Unless not
4501 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00004502 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00004503#ifdef FEAT_MBYTE
4504 && !write_info.bw_conv_error
4505#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004506 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4507 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004508 {
4509 unchanged(buf, TRUE);
4510 u_unchanged(buf);
4511 }
4512
4513 /*
4514 * If written to the current file, update the timestamp of the swap file
4515 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4516 */
4517 if (overwriting)
4518 {
4519 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00004520 if (append)
4521 buf->b_flags &= ~BF_NEW;
4522 else
4523 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004524 }
4525
4526 /*
4527 * If we kept a backup until now, and we are in patch mode, then we make
4528 * the backup file our 'original' file.
4529 */
4530 if (*p_pm && dobackup)
4531 {
4532 char *org = (char *)buf_modname(
4533#ifdef SHORT_FNAME
4534 TRUE,
4535#else
4536 (buf->b_p_sn || buf->b_shortname),
4537#endif
4538 fname, p_pm, FALSE);
4539
4540 if (backup != NULL)
4541 {
4542 struct stat st;
4543
4544 /*
4545 * If the original file does not exist yet
4546 * the current backup file becomes the original file
4547 */
4548 if (org == NULL)
4549 EMSG(_("E205: Patchmode: can't save original file"));
4550 else if (mch_stat(org, &st) < 0)
4551 {
4552 vim_rename(backup, (char_u *)org);
4553 vim_free(backup); /* don't delete the file */
4554 backup = NULL;
4555#ifdef UNIX
4556 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4557#endif
4558 }
4559 }
4560 /*
4561 * If there is no backup file, remember that a (new) file was
4562 * created.
4563 */
4564 else
4565 {
4566 int empty_fd;
4567
4568 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00004569 || (empty_fd = mch_open(org,
4570 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004571 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004572 EMSG(_("E206: patchmode: can't touch empty original file"));
4573 else
4574 close(empty_fd);
4575 }
4576 if (org != NULL)
4577 {
4578 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4579 vim_free(org);
4580 }
4581 }
4582
4583 /*
4584 * Remove the backup unless 'backup' option is set
4585 */
4586 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4587 EMSG(_("E207: Can't delete backup file"));
4588
4589#ifdef FEAT_SUN_WORKSHOP
4590 if (usingSunWorkShop)
4591 workshop_file_saved((char *) ffname);
4592#endif
4593
4594 goto nofail;
4595
4596 /*
4597 * Finish up. We get here either after failure or success.
4598 */
4599fail:
4600 --no_wait_return; /* may wait for return now */
4601nofail:
4602
4603 /* Done saving, we accept changed buffer warnings again */
4604 buf->b_saving = FALSE;
4605
4606 vim_free(backup);
4607 if (buffer != smallbuf)
4608 vim_free(buffer);
4609#ifdef FEAT_MBYTE
4610 vim_free(fenc_tofree);
4611 vim_free(write_info.bw_conv_buf);
4612# ifdef USE_ICONV
4613 if (write_info.bw_iconv_fd != (iconv_t)-1)
4614 {
4615 iconv_close(write_info.bw_iconv_fd);
4616 write_info.bw_iconv_fd = (iconv_t)-1;
4617 }
4618# endif
4619#endif
4620#ifdef HAVE_ACL
4621 mch_free_acl(acl);
4622#endif
4623
4624 if (errmsg != NULL)
4625 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004626 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004627
4628 attr = hl_attr(HLF_E); /* set highlight for error messages */
4629 msg_add_fname(buf,
4630#ifndef UNIX
4631 sfname
4632#else
4633 fname
4634#endif
4635 ); /* put file name in IObuff with quotes */
4636 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4637 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4638 /* If the error message has the form "is ...", put the error number in
4639 * front of the file name. */
4640 if (errnum != NULL)
4641 {
4642 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4643 mch_memmove(IObuff, errnum, (size_t)numlen);
4644 }
4645 STRCAT(IObuff, errmsg);
4646 emsg(IObuff);
4647
4648 retval = FAIL;
4649 if (end == 0)
4650 {
4651 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4652 attr | MSG_HIST);
4653 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4654 attr | MSG_HIST);
4655
4656 /* Update the timestamp to avoid an "overwrite changed file"
4657 * prompt when writing again. */
4658 if (mch_stat((char *)fname, &st_old) >= 0)
4659 {
4660 buf_store_time(buf, &st_old, fname);
4661 buf->b_mtime_read = buf->b_mtime;
4662 }
4663 }
4664 }
4665 msg_scroll = msg_save;
4666
4667#ifdef FEAT_AUTOCMD
4668#ifdef FEAT_EVAL
4669 if (!should_abort(retval))
4670#else
4671 if (!got_int)
4672#endif
4673 {
4674 aco_save_T aco;
4675
4676 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4677
4678 /*
4679 * Apply POST autocommands.
4680 * Careful: The autocommands may call buf_write() recursively!
4681 */
4682 aucmd_prepbuf(&aco, buf);
4683
4684 if (append)
4685 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4686 FALSE, curbuf, eap);
4687 else if (filtering)
4688 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4689 FALSE, curbuf, eap);
4690 else if (reset_changed && whole)
4691 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4692 FALSE, curbuf, eap);
4693 else
4694 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4695 FALSE, curbuf, eap);
4696
4697 /* restore curwin/curbuf and a few other things */
4698 aucmd_restbuf(&aco);
4699
4700#ifdef FEAT_EVAL
4701 if (aborting()) /* autocmds may abort script processing */
4702 retval = FALSE;
4703#endif
4704 }
4705#endif
4706
4707 got_int |= prev_got_int;
4708
4709#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4710 /* Update machine specific information. */
4711 mch_post_buffer_write(buf);
4712#endif
4713 return retval;
4714}
4715
4716/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004717 * Set the name of the current buffer. Use when the buffer doesn't have a
4718 * name and a ":r" or ":w" command with a file name is used.
4719 */
4720 static int
4721set_rw_fname(fname, sfname)
4722 char_u *fname;
4723 char_u *sfname;
4724{
4725#ifdef FEAT_AUTOCMD
4726 /* It's like the unnamed buffer is deleted.... */
4727 if (curbuf->b_p_bl)
4728 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
4729 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
4730# ifdef FEAT_EVAL
4731 if (aborting()) /* autocmds may abort script processing */
4732 return FAIL;
4733# endif
4734#endif
4735
4736 if (setfname(curbuf, fname, sfname, FALSE) == OK)
4737 curbuf->b_flags |= BF_NOTEDITED;
4738
4739#ifdef FEAT_AUTOCMD
4740 /* ....and a new named one is created */
4741 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
4742 if (curbuf->b_p_bl)
4743 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
4744# ifdef FEAT_EVAL
4745 if (aborting()) /* autocmds may abort script processing */
4746 return FAIL;
4747# endif
4748
4749 /* Do filetype detection now if 'filetype' is empty. */
4750 if (*curbuf->b_p_ft == NUL)
4751 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004752 if (au_has_group((char_u *)"filetypedetect"))
Bram Moolenaar70836c82006-02-20 21:28:49 +00004753 (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE);
Bram Moolenaara3227e22006-03-08 21:32:40 +00004754 do_modelines(0);
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004755 }
4756#endif
4757
4758 return OK;
4759}
4760
4761/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004762 * Put file name into IObuff with quotes.
4763 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004764 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004765msg_add_fname(buf, fname)
4766 buf_T *buf;
4767 char_u *fname;
4768{
4769 if (fname == NULL)
4770 fname = (char_u *)"-stdin-";
4771 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4772 IObuff[0] = '"';
4773 STRCAT(IObuff, "\" ");
4774}
4775
4776/*
4777 * Append message for text mode to IObuff.
4778 * Return TRUE if something appended.
4779 */
4780 static int
4781msg_add_fileformat(eol_type)
4782 int eol_type;
4783{
4784#ifndef USE_CRNL
4785 if (eol_type == EOL_DOS)
4786 {
4787 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4788 return TRUE;
4789 }
4790#endif
4791#ifndef USE_CR
4792 if (eol_type == EOL_MAC)
4793 {
4794 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4795 return TRUE;
4796 }
4797#endif
4798#if defined(USE_CRNL) || defined(USE_CR)
4799 if (eol_type == EOL_UNIX)
4800 {
4801 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4802 return TRUE;
4803 }
4804#endif
4805 return FALSE;
4806}
4807
4808/*
4809 * Append line and character count to IObuff.
4810 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004811 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004812msg_add_lines(insert_space, lnum, nchars)
4813 int insert_space;
4814 long lnum;
4815 long nchars;
4816{
4817 char_u *p;
4818
4819 p = IObuff + STRLEN(IObuff);
4820
4821 if (insert_space)
4822 *p++ = ' ';
4823 if (shortmess(SHM_LINES))
4824 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4825 else
4826 {
4827 if (lnum == 1)
4828 STRCPY(p, _("1 line, "));
4829 else
4830 sprintf((char *)p, _("%ld lines, "), lnum);
4831 p += STRLEN(p);
4832 if (nchars == 1)
4833 STRCPY(p, _("1 character"));
4834 else
4835 sprintf((char *)p, _("%ld characters"), nchars);
4836 }
4837}
4838
4839/*
4840 * Append message for missing line separator to IObuff.
4841 */
4842 static void
4843msg_add_eol()
4844{
4845 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4846}
4847
4848/*
4849 * Check modification time of file, before writing to it.
4850 * The size isn't checked, because using a tool like "gzip" takes care of
4851 * using the same timestamp but can't set the size.
4852 */
4853 static int
4854check_mtime(buf, st)
4855 buf_T *buf;
4856 struct stat *st;
4857{
4858 if (buf->b_mtime_read != 0
4859 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4860 {
4861 msg_scroll = TRUE; /* don't overwrite messages here */
4862 msg_silent = 0; /* must give this prompt */
4863 /* don't use emsg() here, don't want to flush the buffers */
4864 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4865 hl_attr(HLF_E));
4866 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4867 TRUE) == 'n')
4868 return FAIL;
4869 msg_scroll = FALSE; /* always overwrite the file message now */
4870 }
4871 return OK;
4872}
4873
4874 static int
4875time_differs(t1, t2)
4876 long t1, t2;
4877{
4878#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4879 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4880 * the seconds. Since the roundoff is done when flushing the inode, the
4881 * time may change unexpectedly by one second!!! */
4882 return (t1 - t2 > 1 || t2 - t1 > 1);
4883#else
4884 return (t1 != t2);
4885#endif
4886}
4887
4888/*
4889 * Call write() to write a number of bytes to the file.
4890 * Also handles encryption and 'encoding' conversion.
4891 *
4892 * Return FAIL for failure, OK otherwise.
4893 */
4894 static int
4895buf_write_bytes(ip)
4896 struct bw_info *ip;
4897{
4898 int wlen;
4899 char_u *buf = ip->bw_buf; /* data to write */
4900 int len = ip->bw_len; /* length of data */
4901#ifdef HAS_BW_FLAGS
4902 int flags = ip->bw_flags; /* extra flags */
4903#endif
4904
4905#ifdef FEAT_MBYTE
4906 /*
4907 * Skip conversion when writing the crypt magic number or the BOM.
4908 */
4909 if (!(flags & FIO_NOCONVERT))
4910 {
4911 char_u *p;
4912 unsigned c;
4913 int n;
4914
4915 if (flags & FIO_UTF8)
4916 {
4917 /*
4918 * Convert latin1 in the buffer to UTF-8 in the file.
4919 */
4920 p = ip->bw_conv_buf; /* translate to buffer */
4921 for (wlen = 0; wlen < len; ++wlen)
4922 p += utf_char2bytes(buf[wlen], p);
4923 buf = ip->bw_conv_buf;
4924 len = (int)(p - ip->bw_conv_buf);
4925 }
4926 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4927 {
4928 /*
4929 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4930 * Latin1 chars in the file.
4931 */
4932 if (flags & FIO_LATIN1)
4933 p = buf; /* translate in-place (can only get shorter) */
4934 else
4935 p = ip->bw_conv_buf; /* translate to buffer */
4936 for (wlen = 0; wlen < len; wlen += n)
4937 {
4938 if (wlen == 0 && ip->bw_restlen != 0)
4939 {
4940 int l;
4941
4942 /* Use remainder of previous call. Append the start of
4943 * buf[] to get a full sequence. Might still be too
4944 * short! */
4945 l = CONV_RESTLEN - ip->bw_restlen;
4946 if (l > len)
4947 l = len;
4948 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004949 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950 if (n > ip->bw_restlen + len)
4951 {
4952 /* We have an incomplete byte sequence at the end to
4953 * be written. We can't convert it without the
4954 * remaining bytes. Keep them for the next call. */
4955 if (ip->bw_restlen + len > CONV_RESTLEN)
4956 return FAIL;
4957 ip->bw_restlen += len;
4958 break;
4959 }
4960 if (n > 1)
4961 c = utf_ptr2char(ip->bw_rest);
4962 else
4963 c = ip->bw_rest[0];
4964 if (n >= ip->bw_restlen)
4965 {
4966 n -= ip->bw_restlen;
4967 ip->bw_restlen = 0;
4968 }
4969 else
4970 {
4971 ip->bw_restlen -= n;
4972 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4973 (size_t)ip->bw_restlen);
4974 n = 0;
4975 }
4976 }
4977 else
4978 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004979 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004980 if (n > len - wlen)
4981 {
4982 /* We have an incomplete byte sequence at the end to
4983 * be written. We can't convert it without the
4984 * remaining bytes. Keep them for the next call. */
4985 if (len - wlen > CONV_RESTLEN)
4986 return FAIL;
4987 ip->bw_restlen = len - wlen;
4988 mch_memmove(ip->bw_rest, buf + wlen,
4989 (size_t)ip->bw_restlen);
4990 break;
4991 }
4992 if (n > 1)
4993 c = utf_ptr2char(buf + wlen);
4994 else
4995 c = buf[wlen];
4996 }
4997
4998 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4999 }
5000 if (flags & FIO_LATIN1)
5001 len = (int)(p - buf);
5002 else
5003 {
5004 buf = ip->bw_conv_buf;
5005 len = (int)(p - ip->bw_conv_buf);
5006 }
5007 }
5008
5009# ifdef WIN3264
5010 else if (flags & FIO_CODEPAGE)
5011 {
5012 /*
5013 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
5014 * codepage.
5015 */
5016 char_u *from;
5017 size_t fromlen;
5018 char_u *to;
5019 int u8c;
5020 BOOL bad = FALSE;
5021 int needed;
5022
5023 if (ip->bw_restlen > 0)
5024 {
5025 /* Need to concatenate the remainder of the previous call and
5026 * the bytes of the current call. Use the end of the
5027 * conversion buffer for this. */
5028 fromlen = len + ip->bw_restlen;
5029 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5030 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5031 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5032 }
5033 else
5034 {
5035 from = buf;
5036 fromlen = len;
5037 }
5038
5039 to = ip->bw_conv_buf;
5040 if (enc_utf8)
5041 {
5042 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
5043 * The buffer has been allocated to be big enough. */
5044 while (fromlen > 0)
5045 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005046 n = (int)utf_ptr2len_len(from, (int)fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047 if (n > (int)fromlen) /* incomplete byte sequence */
5048 break;
5049 u8c = utf_ptr2char(from);
5050 *to++ = (u8c & 0xff);
5051 *to++ = (u8c >> 8);
5052 fromlen -= n;
5053 from += n;
5054 }
5055
5056 /* Copy remainder to ip->bw_rest[] to be used for the next
5057 * call. */
5058 if (fromlen > CONV_RESTLEN)
5059 {
5060 /* weird overlong sequence */
5061 ip->bw_conv_error = TRUE;
5062 return FAIL;
5063 }
5064 mch_memmove(ip->bw_rest, from, fromlen);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005065 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005066 }
5067 else
5068 {
5069 /* Convert from enc_codepage to UCS-2, to the start of the
5070 * buffer. The buffer has been allocated to be big enough. */
5071 ip->bw_restlen = 0;
5072 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005073 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005074 NULL, 0);
5075 if (needed == 0)
5076 {
5077 /* When conversion fails there may be a trailing byte. */
5078 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005079 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080 NULL, 0);
5081 if (needed == 0)
5082 {
5083 /* Conversion doesn't work. */
5084 ip->bw_conv_error = TRUE;
5085 return FAIL;
5086 }
5087 /* Save the trailing byte for the next call. */
5088 ip->bw_rest[0] = from[fromlen - 1];
5089 ip->bw_restlen = 1;
5090 }
5091 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005092 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005093 (LPWSTR)to, needed);
5094 if (needed == 0)
5095 {
5096 /* Safety check: Conversion doesn't work. */
5097 ip->bw_conv_error = TRUE;
5098 return FAIL;
5099 }
5100 to += needed * 2;
5101 }
5102
5103 fromlen = to - ip->bw_conv_buf;
5104 buf = to;
5105# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5106 if (FIO_GET_CP(flags) == CP_UTF8)
5107 {
5108 /* Convert from UCS-2 to UTF-8, using the remainder of the
5109 * conversion buffer. Fails when out of space. */
5110 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
5111 {
5112 u8c = *from++;
5113 u8c += (*from++ << 8);
5114 to += utf_char2bytes(u8c, to);
5115 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
5116 {
5117 ip->bw_conv_error = TRUE;
5118 return FAIL;
5119 }
5120 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005121 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005122 }
5123 else
5124#endif
5125 {
5126 /* Convert from UCS-2 to the codepage, using the remainder of
5127 * the conversion buffer. If the conversion uses the default
5128 * character "0", the data doesn't fit in this encoding, so
5129 * fail. */
5130 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5131 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005132 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0,
5133 &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005134 if (bad)
5135 {
5136 ip->bw_conv_error = TRUE;
5137 return FAIL;
5138 }
5139 }
5140 }
5141# endif
5142
Bram Moolenaar56718732006-03-15 22:53:57 +00005143# ifdef MACOS_CONVERT
Bram Moolenaar071d4272004-06-13 20:20:40 +00005144 else if (flags & FIO_MACROMAN)
5145 {
5146 /*
5147 * Convert UTF-8 or latin1 to Apple MacRoman.
5148 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149 char_u *from;
5150 size_t fromlen;
5151
5152 if (ip->bw_restlen > 0)
5153 {
5154 /* Need to concatenate the remainder of the previous call and
5155 * the bytes of the current call. Use the end of the
5156 * conversion buffer for this. */
5157 fromlen = len + ip->bw_restlen;
5158 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5159 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
5160 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
5161 }
5162 else
5163 {
5164 from = buf;
5165 fromlen = len;
5166 }
5167
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005168 if (enc2macroman(from, fromlen,
5169 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5170 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005171 {
5172 ip->bw_conv_error = TRUE;
5173 return FAIL;
5174 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005175 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005176 }
5177# endif
5178
5179# ifdef USE_ICONV
5180 if (ip->bw_iconv_fd != (iconv_t)-1)
5181 {
5182 const char *from;
5183 size_t fromlen;
5184 char *to;
5185 size_t tolen;
5186
5187 /* Convert with iconv(). */
5188 if (ip->bw_restlen > 0)
5189 {
5190 /* Need to concatenate the remainder of the previous call and
5191 * the bytes of the current call. Use the end of the
5192 * conversion buffer for this. */
5193 fromlen = len + ip->bw_restlen;
5194 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5195 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
5196 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
5197 tolen = ip->bw_conv_buflen - fromlen;
5198 }
5199 else
5200 {
5201 from = (const char *)buf;
5202 fromlen = len;
5203 tolen = ip->bw_conv_buflen;
5204 }
5205 to = (char *)ip->bw_conv_buf;
5206
5207 if (ip->bw_first)
5208 {
5209 size_t save_len = tolen;
5210
5211 /* output the initial shift state sequence */
5212 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5213
5214 /* There is a bug in iconv() on Linux (which appears to be
5215 * wide-spread) which sets "to" to NULL and messes up "tolen".
5216 */
5217 if (to == NULL)
5218 {
5219 to = (char *)ip->bw_conv_buf;
5220 tolen = save_len;
5221 }
5222 ip->bw_first = FALSE;
5223 }
5224
5225 /*
5226 * If iconv() has an error or there is not enough room, fail.
5227 */
5228 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5229 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5230 || fromlen > CONV_RESTLEN)
5231 {
5232 ip->bw_conv_error = TRUE;
5233 return FAIL;
5234 }
5235
5236 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5237 if (fromlen > 0)
5238 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5239 ip->bw_restlen = (int)fromlen;
5240
5241 buf = ip->bw_conv_buf;
5242 len = (int)((char_u *)to - ip->bw_conv_buf);
5243 }
5244# endif
5245 }
5246#endif /* FEAT_MBYTE */
5247
5248#ifdef FEAT_CRYPT
5249 if (flags & FIO_ENCRYPTED) /* encrypt the data */
5250 {
5251 int ztemp, t, i;
5252
5253 for (i = 0; i < len; i++)
5254 {
5255 ztemp = buf[i];
5256 buf[i] = ZENCODE(ztemp, t);
5257 }
5258 }
5259#endif
5260
5261 /* Repeat the write(), it may be interrupted by a signal. */
Bram Moolenaar36f5ac02007-05-06 12:40:34 +00005262 while (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005263 {
5264 wlen = vim_write(ip->bw_fd, buf, len);
5265 if (wlen <= 0) /* error! */
5266 return FAIL;
5267 len -= wlen;
5268 buf += wlen;
5269 }
5270 return OK;
5271}
5272
5273#ifdef FEAT_MBYTE
5274/*
5275 * Convert a Unicode character to bytes.
5276 */
5277 static int
5278ucs2bytes(c, pp, flags)
5279 unsigned c; /* in: character */
5280 char_u **pp; /* in/out: pointer to result */
5281 int flags; /* FIO_ flags */
5282{
5283 char_u *p = *pp;
5284 int error = FALSE;
5285 int cc;
5286
5287
5288 if (flags & FIO_UCS4)
5289 {
5290 if (flags & FIO_ENDIAN_L)
5291 {
5292 *p++ = c;
5293 *p++ = (c >> 8);
5294 *p++ = (c >> 16);
5295 *p++ = (c >> 24);
5296 }
5297 else
5298 {
5299 *p++ = (c >> 24);
5300 *p++ = (c >> 16);
5301 *p++ = (c >> 8);
5302 *p++ = c;
5303 }
5304 }
5305 else if (flags & (FIO_UCS2 | FIO_UTF16))
5306 {
5307 if (c >= 0x10000)
5308 {
5309 if (flags & FIO_UTF16)
5310 {
5311 /* Make two words, ten bits of the character in each. First
5312 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5313 c -= 0x10000;
5314 if (c >= 0x100000)
5315 error = TRUE;
5316 cc = ((c >> 10) & 0x3ff) + 0xd800;
5317 if (flags & FIO_ENDIAN_L)
5318 {
5319 *p++ = cc;
5320 *p++ = ((unsigned)cc >> 8);
5321 }
5322 else
5323 {
5324 *p++ = ((unsigned)cc >> 8);
5325 *p++ = cc;
5326 }
5327 c = (c & 0x3ff) + 0xdc00;
5328 }
5329 else
5330 error = TRUE;
5331 }
5332 if (flags & FIO_ENDIAN_L)
5333 {
5334 *p++ = c;
5335 *p++ = (c >> 8);
5336 }
5337 else
5338 {
5339 *p++ = (c >> 8);
5340 *p++ = c;
5341 }
5342 }
5343 else /* Latin1 */
5344 {
5345 if (c >= 0x100)
5346 {
5347 error = TRUE;
5348 *p++ = 0xBF;
5349 }
5350 else
5351 *p++ = c;
5352 }
5353
5354 *pp = p;
5355 return error;
5356}
5357
5358/*
5359 * Return TRUE if "a" and "b" are the same 'encoding'.
5360 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5361 */
5362 static int
5363same_encoding(a, b)
5364 char_u *a;
5365 char_u *b;
5366{
5367 int f;
5368
5369 if (STRCMP(a, b) == 0)
5370 return TRUE;
5371 f = get_fio_flags(a);
5372 return (f != 0 && get_fio_flags(b) == f);
5373}
5374
5375/*
5376 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5377 * internal conversion.
5378 * if "ptr" is an empty string, use 'encoding'.
5379 */
5380 static int
5381get_fio_flags(ptr)
5382 char_u *ptr;
5383{
5384 int prop;
5385
5386 if (*ptr == NUL)
5387 ptr = p_enc;
5388
5389 prop = enc_canon_props(ptr);
5390 if (prop & ENC_UNICODE)
5391 {
5392 if (prop & ENC_2BYTE)
5393 {
5394 if (prop & ENC_ENDIAN_L)
5395 return FIO_UCS2 | FIO_ENDIAN_L;
5396 return FIO_UCS2;
5397 }
5398 if (prop & ENC_4BYTE)
5399 {
5400 if (prop & ENC_ENDIAN_L)
5401 return FIO_UCS4 | FIO_ENDIAN_L;
5402 return FIO_UCS4;
5403 }
5404 if (prop & ENC_2WORD)
5405 {
5406 if (prop & ENC_ENDIAN_L)
5407 return FIO_UTF16 | FIO_ENDIAN_L;
5408 return FIO_UTF16;
5409 }
5410 return FIO_UTF8;
5411 }
5412 if (prop & ENC_LATIN1)
5413 return FIO_LATIN1;
5414 /* must be ENC_DBCS, requires iconv() */
5415 return 0;
5416}
5417
5418#ifdef WIN3264
5419/*
5420 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5421 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5422 * Used for conversion between 'encoding' and 'fileencoding'.
5423 */
5424 static int
5425get_win_fio_flags(ptr)
5426 char_u *ptr;
5427{
5428 int cp;
5429
5430 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5431 if (!enc_utf8 && enc_codepage <= 0)
5432 return 0;
5433
5434 cp = encname2codepage(ptr);
5435 if (cp == 0)
5436 {
5437# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5438 if (STRCMP(ptr, "utf-8") == 0)
5439 cp = CP_UTF8;
5440 else
5441# endif
5442 return 0;
5443 }
5444 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5445}
5446#endif
5447
5448#ifdef MACOS_X
5449/*
5450 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5451 * needed for the internal conversion to/from utf-8 or latin1.
5452 */
5453 static int
5454get_mac_fio_flags(ptr)
5455 char_u *ptr;
5456{
5457 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5458 && (enc_canon_props(ptr) & ENC_MACROMAN))
5459 return FIO_MACROMAN;
5460 return 0;
5461}
5462#endif
5463
5464/*
5465 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5466 * "size" must be at least 2.
5467 * Return the name of the encoding and set "*lenp" to the length.
5468 * Returns NULL when no BOM found.
5469 */
5470 static char_u *
5471check_for_bom(p, size, lenp, flags)
5472 char_u *p;
5473 long size;
5474 int *lenp;
5475 int flags;
5476{
5477 char *name = NULL;
5478 int len = 2;
5479
5480 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5481 && (flags == FIO_ALL || flags == 0))
5482 {
5483 name = "utf-8"; /* EF BB BF */
5484 len = 3;
5485 }
5486 else if (p[0] == 0xff && p[1] == 0xfe)
5487 {
5488 if (size >= 4 && p[2] == 0 && p[3] == 0
5489 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5490 {
5491 name = "ucs-4le"; /* FF FE 00 00 */
5492 len = 4;
5493 }
5494 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5495 name = "ucs-2le"; /* FF FE */
5496 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5497 name = "utf-16le"; /* FF FE */
5498 }
5499 else if (p[0] == 0xfe && p[1] == 0xff
5500 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5501 {
5502 if (flags == FIO_UTF16)
5503 name = "utf-16"; /* FE FF */
5504 else
5505 name = "ucs-2"; /* FE FF */
5506 }
5507 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5508 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5509 {
5510 name = "ucs-4"; /* 00 00 FE FF */
5511 len = 4;
5512 }
5513
5514 *lenp = len;
5515 return (char_u *)name;
5516}
5517
5518/*
5519 * Generate a BOM in "buf[4]" for encoding "name".
5520 * Return the length of the BOM (zero when no BOM).
5521 */
5522 static int
5523make_bom(buf, name)
5524 char_u *buf;
5525 char_u *name;
5526{
5527 int flags;
5528 char_u *p;
5529
5530 flags = get_fio_flags(name);
5531
5532 /* Can't put a BOM in a non-Unicode file. */
5533 if (flags == FIO_LATIN1 || flags == 0)
5534 return 0;
5535
5536 if (flags == FIO_UTF8) /* UTF-8 */
5537 {
5538 buf[0] = 0xef;
5539 buf[1] = 0xbb;
5540 buf[2] = 0xbf;
5541 return 3;
5542 }
5543 p = buf;
5544 (void)ucs2bytes(0xfeff, &p, flags);
5545 return (int)(p - buf);
5546}
5547#endif
5548
5549/*
5550 * Try to find a shortname by comparing the fullname with the current
5551 * directory.
5552 * Returns NULL if not shorter name possible, pointer into "full_path"
5553 * otherwise.
5554 */
5555 char_u *
5556shorten_fname(full_path, dir_name)
5557 char_u *full_path;
5558 char_u *dir_name;
5559{
5560 int len;
5561 char_u *p;
5562
5563 if (full_path == NULL)
5564 return NULL;
5565 len = (int)STRLEN(dir_name);
5566 if (fnamencmp(dir_name, full_path, len) == 0)
5567 {
5568 p = full_path + len;
5569#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5570 /*
5571 * MSDOS: when a file is in the root directory, dir_name will end in a
5572 * slash, since C: by itself does not define a specific dir. In this
5573 * case p may already be correct. <negri>
5574 */
5575 if (!((len > 2) && (*(p - 2) == ':')))
5576#endif
5577 {
5578 if (vim_ispathsep(*p))
5579 ++p;
5580#ifndef VMS /* the path separator is always part of the path */
5581 else
5582 p = NULL;
5583#endif
5584 }
5585 }
5586#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5587 /*
5588 * When using a file in the current drive, remove the drive name:
5589 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5590 * a floppy from "A:\dir" to "B:\dir".
5591 */
5592 else if (len > 3
5593 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5594 && full_path[1] == ':'
5595 && vim_ispathsep(full_path[2]))
5596 p = full_path + 2;
5597#endif
5598 else
5599 p = NULL;
5600 return p;
5601}
5602
5603/*
5604 * Shorten filenames for all buffers.
5605 * When "force" is TRUE: Use full path from now on for files currently being
5606 * edited, both for file name and swap file name. Try to shorten the file
5607 * names a bit, if safe to do so.
5608 * When "force" is FALSE: Only try to shorten absolute file names.
5609 * For buffers that have buftype "nofile" or "scratch": never change the file
5610 * name.
5611 */
5612 void
5613shorten_fnames(force)
5614 int force;
5615{
5616 char_u dirname[MAXPATHL];
5617 buf_T *buf;
5618 char_u *p;
5619
5620 mch_dirname(dirname, MAXPATHL);
5621 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5622 {
5623 if (buf->b_fname != NULL
5624#ifdef FEAT_QUICKFIX
5625 && !bt_nofile(buf)
5626#endif
5627 && !path_with_url(buf->b_fname)
5628 && (force
5629 || buf->b_sfname == NULL
5630 || mch_isFullName(buf->b_sfname)))
5631 {
5632 vim_free(buf->b_sfname);
5633 buf->b_sfname = NULL;
5634 p = shorten_fname(buf->b_ffname, dirname);
5635 if (p != NULL)
5636 {
5637 buf->b_sfname = vim_strsave(p);
5638 buf->b_fname = buf->b_sfname;
5639 }
5640 if (p == NULL || buf->b_fname == NULL)
5641 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005642 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005643
5644 /* Always make the swap file name a full path, a "nofile" buffer may
5645 * also have a swap file. */
5646 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005647 }
5648#ifdef FEAT_WINDOWS
5649 status_redraw_all();
Bram Moolenaar49d7bf12006-02-17 21:45:41 +00005650 redraw_tabline = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005651#endif
5652}
5653
5654#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5655 || defined(FEAT_GUI_MSWIN) \
5656 || defined(FEAT_GUI_MAC) \
5657 || defined(PROTO)
5658/*
5659 * Shorten all filenames in "fnames[count]" by current directory.
5660 */
5661 void
5662shorten_filenames(fnames, count)
5663 char_u **fnames;
5664 int count;
5665{
5666 int i;
5667 char_u dirname[MAXPATHL];
5668 char_u *p;
5669
5670 if (fnames == NULL || count < 1)
5671 return;
5672 mch_dirname(dirname, sizeof(dirname));
5673 for (i = 0; i < count; ++i)
5674 {
5675 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5676 {
5677 /* shorten_fname() returns pointer in given "fnames[i]". If free
5678 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5679 * "p" first then free fnames[i]. */
5680 p = vim_strsave(p);
5681 vim_free(fnames[i]);
5682 fnames[i] = p;
5683 }
5684 }
5685}
5686#endif
5687
5688/*
5689 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5690 * fo_o_h.ext for MSDOS or when shortname option set.
5691 *
5692 * Assumed that fname is a valid name found in the filesystem we assure that
5693 * the return value is a different name and ends in 'ext'.
5694 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5695 * characters otherwise.
5696 * Space for the returned name is allocated, must be freed later.
5697 * Returns NULL when out of memory.
5698 */
5699 char_u *
5700modname(fname, ext, prepend_dot)
5701 char_u *fname, *ext;
5702 int prepend_dot; /* may prepend a '.' to file name */
5703{
5704 return buf_modname(
5705#ifdef SHORT_FNAME
5706 TRUE,
5707#else
5708 (curbuf->b_p_sn || curbuf->b_shortname),
5709#endif
5710 fname, ext, prepend_dot);
5711}
5712
5713 char_u *
5714buf_modname(shortname, fname, ext, prepend_dot)
5715 int shortname; /* use 8.3 file name */
5716 char_u *fname, *ext;
5717 int prepend_dot; /* may prepend a '.' to file name */
5718{
5719 char_u *retval;
5720 char_u *s;
5721 char_u *e;
5722 char_u *ptr;
5723 int fnamelen, extlen;
5724
5725 extlen = (int)STRLEN(ext);
5726
5727 /*
5728 * If there is no file name we must get the name of the current directory
5729 * (we need the full path in case :cd is used).
5730 */
5731 if (fname == NULL || *fname == NUL)
5732 {
5733 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5734 if (retval == NULL)
5735 return NULL;
5736 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5737 (fnamelen = (int)STRLEN(retval)) == 0)
5738 {
5739 vim_free(retval);
5740 return NULL;
5741 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005742 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005743 {
5744 retval[fnamelen++] = PATHSEP;
5745 retval[fnamelen] = NUL;
5746 }
5747#ifndef SHORT_FNAME
5748 prepend_dot = FALSE; /* nothing to prepend a dot to */
5749#endif
5750 }
5751 else
5752 {
5753 fnamelen = (int)STRLEN(fname);
5754 retval = alloc((unsigned)(fnamelen + extlen + 3));
5755 if (retval == NULL)
5756 return NULL;
5757 STRCPY(retval, fname);
5758#ifdef VMS
5759 vms_remove_version(retval); /* we do not need versions here */
5760#endif
5761 }
5762
5763 /*
5764 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5765 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5766 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5767 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5768 */
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005769 for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005770 {
5771#ifndef RISCOS
5772 if (*ext == '.'
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005773# ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005774 && (!USE_LONG_FNAME || shortname)
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005775# else
5776# ifndef SHORT_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005777 && shortname
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005778# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005779# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005780 )
5781 if (*ptr == '.') /* replace '.' by '_' */
5782 *ptr = '_';
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005783#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005784 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005785 {
5786 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005787 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005788 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005789 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005790
5791 /* the file name has at most BASENAMELEN characters. */
5792#ifndef SHORT_FNAME
5793 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5794 ptr[BASENAMELEN] = '\0';
5795#endif
5796
5797 s = ptr + STRLEN(ptr);
5798
5799 /*
5800 * For 8.3 file names we may have to reduce the length.
5801 */
5802#ifdef USE_LONG_FNAME
5803 if (!USE_LONG_FNAME || shortname)
5804#else
5805# ifndef SHORT_FNAME
5806 if (shortname)
5807# endif
5808#endif
5809 {
5810 /*
5811 * If there is no file name, or the file name ends in '/', and the
5812 * extension starts with '.', put a '_' before the dot, because just
5813 * ".ext" is invalid.
5814 */
5815 if (fname == NULL || *fname == NUL
5816 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5817 {
5818#ifdef RISCOS
5819 if (*ext == '/')
5820#else
5821 if (*ext == '.')
5822#endif
5823 *s++ = '_';
5824 }
5825 /*
5826 * If the extension starts with '.', truncate the base name at 8
5827 * characters
5828 */
5829#ifdef RISCOS
5830 /* We normally use '/', but swap files are '_' */
5831 else if (*ext == '/' || *ext == '_')
5832#else
5833 else if (*ext == '.')
5834#endif
5835 {
5836 if (s - ptr > (size_t)8)
5837 {
5838 s = ptr + 8;
5839 *s = '\0';
5840 }
5841 }
5842 /*
5843 * If the extension doesn't start with '.', and the file name
5844 * doesn't have an extension yet, append a '.'
5845 */
5846#ifdef RISCOS
5847 else if ((e = vim_strchr(ptr, '/')) == NULL)
5848 *s++ = '/';
5849#else
5850 else if ((e = vim_strchr(ptr, '.')) == NULL)
5851 *s++ = '.';
5852#endif
5853 /*
5854 * If the extension doesn't start with '.', and there already is an
Bram Moolenaar7263a772007-05-10 17:35:54 +00005855 * extension, it may need to be truncated
Bram Moolenaar071d4272004-06-13 20:20:40 +00005856 */
5857 else if ((int)STRLEN(e) + extlen > 4)
5858 s = e + 4 - extlen;
5859 }
5860#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5861 /*
5862 * If there is no file name, and the extension starts with '.', put a
5863 * '_' before the dot, because just ".ext" may be invalid if it's on a
5864 * FAT partition, and on HPFS it doesn't matter.
5865 */
5866 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5867 *s++ = '_';
5868#endif
5869
5870 /*
5871 * Append the extention.
5872 * ext can start with '.' and cannot exceed 3 more characters.
5873 */
5874 STRCPY(s, ext);
5875
5876#ifndef SHORT_FNAME
5877 /*
5878 * Prepend the dot.
5879 */
5880 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5881#ifdef RISCOS
5882 '/'
5883#else
5884 '.'
5885#endif
5886#ifdef USE_LONG_FNAME
5887 && USE_LONG_FNAME
5888#endif
5889 )
5890 {
5891 mch_memmove(e + 1, e, STRLEN(e) + 1);
5892#ifdef RISCOS
5893 *e = '/';
5894#else
5895 *e = '.';
5896#endif
5897 }
5898#endif
5899
5900 /*
5901 * Check that, after appending the extension, the file name is really
5902 * different.
5903 */
5904 if (fname != NULL && STRCMP(fname, retval) == 0)
5905 {
5906 /* we search for a character that can be replaced by '_' */
5907 while (--s >= ptr)
5908 {
5909 if (*s != '_')
5910 {
5911 *s = '_';
5912 break;
5913 }
5914 }
5915 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5916 *ptr = 'v';
5917 }
5918 return retval;
5919}
5920
5921/*
5922 * Like fgets(), but if the file line is too long, it is truncated and the
5923 * rest of the line is thrown away. Returns TRUE for end-of-file.
5924 */
5925 int
5926vim_fgets(buf, size, fp)
5927 char_u *buf;
5928 int size;
5929 FILE *fp;
5930{
5931 char *eof;
5932#define FGETS_SIZE 200
5933 char tbuf[FGETS_SIZE];
5934
5935 buf[size - 2] = NUL;
5936#ifdef USE_CR
5937 eof = fgets_cr((char *)buf, size, fp);
5938#else
5939 eof = fgets((char *)buf, size, fp);
5940#endif
5941 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5942 {
5943 buf[size - 1] = NUL; /* Truncate the line */
5944
5945 /* Now throw away the rest of the line: */
5946 do
5947 {
5948 tbuf[FGETS_SIZE - 2] = NUL;
5949#ifdef USE_CR
5950 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5951#else
5952 fgets((char *)tbuf, FGETS_SIZE, fp);
5953#endif
5954 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5955 }
5956 return (eof == NULL);
5957}
5958
5959#if defined(USE_CR) || defined(PROTO)
5960/*
5961 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5962 * Returns TRUE for end-of-file.
5963 * Only used for the Mac, because it's much slower than vim_fgets().
5964 */
5965 int
5966tag_fgets(buf, size, fp)
5967 char_u *buf;
5968 int size;
5969 FILE *fp;
5970{
5971 int i = 0;
5972 int c;
5973 int eof = FALSE;
5974
5975 for (;;)
5976 {
5977 c = fgetc(fp);
5978 if (c == EOF)
5979 {
5980 eof = TRUE;
5981 break;
5982 }
5983 if (c == '\r')
5984 {
5985 /* Always store a NL for end-of-line. */
5986 if (i < size - 1)
5987 buf[i++] = '\n';
5988 c = fgetc(fp);
5989 if (c != '\n') /* Macintosh format: single CR. */
5990 ungetc(c, fp);
5991 break;
5992 }
5993 if (i < size - 1)
5994 buf[i++] = c;
5995 if (c == '\n')
5996 break;
5997 }
5998 buf[i] = NUL;
5999 return eof;
6000}
6001#endif
6002
6003/*
6004 * rename() only works if both files are on the same file system, this
6005 * function will (attempts to?) copy the file across if rename fails -- webb
6006 * Return -1 for failure, 0 for success.
6007 */
6008 int
6009vim_rename(from, to)
6010 char_u *from;
6011 char_u *to;
6012{
6013 int fd_in;
6014 int fd_out;
6015 int n;
6016 char *errmsg = NULL;
6017 char *buffer;
6018#ifdef AMIGA
6019 BPTR flock;
6020#endif
6021 struct stat st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006022 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006023#ifdef HAVE_ACL
6024 vim_acl_T acl; /* ACL from original file */
6025#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006026
6027 /*
6028 * When the names are identical, there is nothing to do.
6029 */
6030 if (fnamecmp(from, to) == 0)
6031 return 0;
6032
6033 /*
6034 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
6035 */
6036 if (mch_stat((char *)from, &st) < 0)
6037 return -1;
6038
6039 /*
6040 * Delete the "to" file, this is required on some systems to make the
6041 * mch_rename() work, on other systems it makes sure that we don't have
6042 * two files when the mch_rename() fails.
6043 */
6044
6045#ifdef AMIGA
6046 /*
6047 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
6048 * that the name of the "to" file is the same as the "from" file, even
Bram Moolenaar7263a772007-05-10 17:35:54 +00006049 * though the names are different. To avoid the chance of accidentally
Bram Moolenaar071d4272004-06-13 20:20:40 +00006050 * deleting the "from" file (horror!) we lock it during the remove.
6051 *
6052 * When used for making a backup before writing the file: This should not
6053 * happen with ":w", because startscript() should detect this problem and
6054 * set buf->b_shortname, causing modname() to return a correct ".bak" file
6055 * name. This problem does exist with ":w filename", but then the
6056 * original file will be somewhere else so the backup isn't really
6057 * important. If autoscripting is off the rename may fail.
6058 */
6059 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
6060#endif
6061 mch_remove(to);
6062#ifdef AMIGA
6063 if (flock)
6064 UnLock(flock);
6065#endif
6066
6067 /*
6068 * First try a normal rename, return if it works.
6069 */
6070 if (mch_rename((char *)from, (char *)to) == 0)
6071 return 0;
6072
6073 /*
6074 * Rename() failed, try copying the file.
6075 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006076 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006077#ifdef HAVE_ACL
6078 /* For systems that support ACL: get the ACL from the original file. */
6079 acl = mch_get_acl(from);
6080#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006081 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
6082 if (fd_in == -1)
6083 return -1;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006084
6085 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00006086 fd_out = mch_open((char *)to,
6087 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006088 if (fd_out == -1)
6089 {
6090 close(fd_in);
6091 return -1;
6092 }
6093
6094 buffer = (char *)alloc(BUFSIZE);
6095 if (buffer == NULL)
6096 {
6097 close(fd_in);
6098 close(fd_out);
6099 return -1;
6100 }
6101
6102 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
6103 if (vim_write(fd_out, buffer, n) != n)
6104 {
6105 errmsg = _("E208: Error writing to \"%s\"");
6106 break;
6107 }
6108
6109 vim_free(buffer);
6110 close(fd_in);
6111 if (close(fd_out) < 0)
6112 errmsg = _("E209: Error closing \"%s\"");
6113 if (n < 0)
6114 {
6115 errmsg = _("E210: Error reading \"%s\"");
6116 to = from;
6117 }
Bram Moolenaar7263a772007-05-10 17:35:54 +00006118#ifndef UNIX /* for Unix mch_open() already set the permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00006119 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00006120#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00006121#ifdef HAVE_ACL
6122 mch_set_acl(to, acl);
6123#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006124 if (errmsg != NULL)
6125 {
6126 EMSG2(errmsg, to);
6127 return -1;
6128 }
6129 mch_remove(from);
6130 return 0;
6131}
6132
6133static int already_warned = FALSE;
6134
6135/*
6136 * Check if any not hidden buffer has been changed.
6137 * Postpone the check if there are characters in the stuff buffer, a global
6138 * command is being executed, a mapping is being executed or an autocommand is
6139 * busy.
6140 * Returns TRUE if some message was written (screen should be redrawn and
6141 * cursor positioned).
6142 */
6143 int
6144check_timestamps(focus)
6145 int focus; /* called for GUI focus event */
6146{
6147 buf_T *buf;
6148 int didit = 0;
6149 int n;
6150
6151 /* Don't check timestamps while system() or another low-level function may
6152 * cause us to lose and gain focus. */
6153 if (no_check_timestamps > 0)
6154 return FALSE;
6155
6156 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6157 * event and we would keep on checking if the file is steadily growing.
6158 * Do check again after typing something. */
6159 if (focus && did_check_timestamps)
6160 {
6161 need_check_timestamps = TRUE;
6162 return FALSE;
6163 }
6164
6165 if (!stuff_empty() || global_busy || !typebuf_typed()
6166#ifdef FEAT_AUTOCMD
Bram Moolenaar5555acc2006-04-07 21:33:12 +00006167 || autocmd_busy || curbuf_lock > 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006168#endif
6169 )
6170 need_check_timestamps = TRUE; /* check later */
6171 else
6172 {
6173 ++no_wait_return;
6174 did_check_timestamps = TRUE;
6175 already_warned = FALSE;
6176 for (buf = firstbuf; buf != NULL; )
6177 {
6178 /* Only check buffers in a window. */
6179 if (buf->b_nwindows > 0)
6180 {
6181 n = buf_check_timestamp(buf, focus);
6182 if (didit < n)
6183 didit = n;
6184 if (n > 0 && !buf_valid(buf))
6185 {
6186 /* Autocommands have removed the buffer, start at the
6187 * first one again. */
6188 buf = firstbuf;
6189 continue;
6190 }
6191 }
6192 buf = buf->b_next;
6193 }
6194 --no_wait_return;
6195 need_check_timestamps = FALSE;
6196 if (need_wait_return && didit == 2)
6197 {
6198 /* make sure msg isn't overwritten */
6199 msg_puts((char_u *)"\n");
6200 out_flush();
6201 }
6202 }
6203 return didit;
6204}
6205
6206/*
6207 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6208 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6209 * empty.
6210 */
6211 static int
6212move_lines(frombuf, tobuf)
6213 buf_T *frombuf;
6214 buf_T *tobuf;
6215{
6216 buf_T *tbuf = curbuf;
6217 int retval = OK;
6218 linenr_T lnum;
6219 char_u *p;
6220
6221 /* Copy the lines in "frombuf" to "tobuf". */
6222 curbuf = tobuf;
6223 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6224 {
6225 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6226 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6227 {
6228 vim_free(p);
6229 retval = FAIL;
6230 break;
6231 }
6232 vim_free(p);
6233 }
6234
6235 /* Delete all the lines in "frombuf". */
6236 if (retval != FAIL)
6237 {
6238 curbuf = frombuf;
Bram Moolenaar9460b9d2007-01-09 14:37:01 +00006239 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum)
6240 if (ml_delete(lnum, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006241 {
6242 /* Oops! We could try putting back the saved lines, but that
6243 * might fail again... */
6244 retval = FAIL;
6245 break;
6246 }
6247 }
6248
6249 curbuf = tbuf;
6250 return retval;
6251}
6252
6253/*
6254 * Check if buffer "buf" has been changed.
6255 * Also check if the file for a new buffer unexpectedly appeared.
6256 * return 1 if a changed buffer was found.
6257 * return 2 if a message has been displayed.
6258 * return 0 otherwise.
6259 */
6260/*ARGSUSED*/
6261 int
6262buf_check_timestamp(buf, focus)
6263 buf_T *buf;
6264 int focus; /* called for GUI focus event */
6265{
6266 struct stat st;
6267 int stat_res;
6268 int retval = 0;
6269 char_u *path;
6270 char_u *tbuf;
6271 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006272 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006273 int helpmesg = FALSE;
6274 int reload = FALSE;
6275#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6276 int can_reload = FALSE;
6277#endif
6278 size_t orig_size = buf->b_orig_size;
6279 int orig_mode = buf->b_orig_mode;
6280#ifdef FEAT_GUI
6281 int save_mouse_correct = need_mouse_correct;
6282#endif
6283#ifdef FEAT_AUTOCMD
6284 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006285 int n;
6286 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006287#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006288 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006289
6290 /* If there is no file name, the buffer is not loaded, 'buftype' is
6291 * set, we are in the middle of a save or being called recursively: ignore
6292 * this buffer. */
6293 if (buf->b_ffname == NULL
6294 || buf->b_ml.ml_mfp == NULL
6295#if defined(FEAT_QUICKFIX)
6296 || *buf->b_p_bt != NUL
6297#endif
6298 || buf->b_saving
6299#ifdef FEAT_AUTOCMD
6300 || busy
6301#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006302#ifdef FEAT_NETBEANS_INTG
6303 || isNetbeansBuffer(buf)
6304#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006305 )
6306 return 0;
6307
6308 if ( !(buf->b_flags & BF_NOTEDITED)
6309 && buf->b_mtime != 0
6310 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6311 || time_differs((long)st.st_mtime, buf->b_mtime)
6312#ifdef HAVE_ST_MODE
6313 || (int)st.st_mode != buf->b_orig_mode
6314#else
6315 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6316#endif
6317 ))
6318 {
6319 retval = 1;
6320
Bram Moolenaar316059c2006-01-14 21:18:42 +00006321 /* set b_mtime to stop further warnings (e.g., when executing
6322 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006323 if (stat_res < 0)
6324 {
6325 buf->b_mtime = 0;
6326 buf->b_orig_size = 0;
6327 buf->b_orig_mode = 0;
6328 }
6329 else
6330 buf_store_time(buf, &st, buf->b_ffname);
6331
6332 /* Don't do anything for a directory. Might contain the file
6333 * explorer. */
6334 if (mch_isdir(buf->b_fname))
6335 ;
6336
6337 /*
6338 * If 'autoread' is set, the buffer has no changes and the file still
6339 * exists, reload the buffer. Use the buffer-local option value if it
6340 * was set, the global option value otherwise.
6341 */
6342 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6343 && !bufIsChanged(buf) && stat_res >= 0)
6344 reload = TRUE;
6345 else
6346 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006347 if (stat_res < 0)
6348 reason = "deleted";
6349 else if (bufIsChanged(buf))
6350 reason = "conflict";
6351 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6352 reason = "changed";
6353 else if (orig_mode != buf->b_orig_mode)
6354 reason = "mode";
6355 else
6356 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006357
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006358#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006359 /*
6360 * Only give the warning if there are no FileChangedShell
6361 * autocommands.
6362 * Avoid being called recursively by setting "busy".
6363 */
6364 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006365# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006366 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6367 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006368# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006369 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6370 buf->b_fname, buf->b_fname, FALSE, buf);
6371 busy = FALSE;
6372 if (n)
6373 {
6374 if (!buf_valid(buf))
6375 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006376# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006377 s = get_vim_var_str(VV_FCS_CHOICE);
6378 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6379 reload = TRUE;
6380 else if (STRCMP(s, "ask") == 0)
6381 n = FALSE;
6382 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006383# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006384 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006385 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006386 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006387#endif
6388 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006389 if (*reason == 'd')
6390 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006391 else
6392 {
6393 helpmesg = TRUE;
6394#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6395 can_reload = TRUE;
6396#endif
6397 /*
6398 * Check if the file contents really changed to avoid
6399 * giving a warning when only the timestamp was set (e.g.,
6400 * checked out of CVS). Always warn when the buffer was
6401 * changed.
6402 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006403 if (reason[2] == 'n')
6404 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006405 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006406 mesg2 = _("See \":help W12\" for more info.");
6407 }
6408 else if (reason[1] == 'h')
6409 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006410 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006411 mesg2 = _("See \":help W11\" for more info.");
6412 }
6413 else if (*reason == 'm')
6414 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006415 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006416 mesg2 = _("See \":help W16\" for more info.");
6417 }
6418 /* Else: only timestamp changed, ignored */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006419 }
6420 }
6421 }
6422
6423 }
6424 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6425 && vim_fexists(buf->b_ffname))
6426 {
6427 retval = 1;
6428 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6429 buf->b_flags |= BF_NEW_W;
6430#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6431 can_reload = TRUE;
6432#endif
6433 }
6434
6435 if (mesg != NULL)
6436 {
6437 path = home_replace_save(buf, buf->b_fname);
6438 if (path != NULL)
6439 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006440 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006441 mesg2 = "";
6442 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6443 + STRLEN(mesg2) + 2));
6444 sprintf((char *)tbuf, mesg, path);
6445#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6446 if (can_reload)
6447 {
6448 if (*mesg2 != NUL)
6449 {
6450 STRCAT(tbuf, "\n");
6451 STRCAT(tbuf, mesg2);
6452 }
6453 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6454 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6455 reload = TRUE;
6456 }
6457 else
6458#endif
6459 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6460 {
6461 if (*mesg2 != NUL)
6462 {
6463 STRCAT(tbuf, "; ");
6464 STRCAT(tbuf, mesg2);
6465 }
6466 EMSG(tbuf);
6467 retval = 2;
6468 }
6469 else
6470 {
Bram Moolenaared203462004-06-16 11:19:22 +00006471# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006472 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006473# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006474 {
6475 msg_start();
6476 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6477 if (*mesg2 != NUL)
6478 msg_puts_attr((char_u *)mesg2,
6479 hl_attr(HLF_W) + MSG_HIST);
6480 msg_clr_eos();
6481 (void)msg_end();
6482 if (emsg_silent == 0)
6483 {
6484 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006485# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006486 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006487# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006488 /* give the user some time to think about it */
6489 ui_delay(1000L, TRUE);
6490
6491 /* don't redraw and erase the message */
6492 redraw_cmdline = FALSE;
6493 }
6494 }
6495 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006496 }
6497
6498 vim_free(path);
6499 vim_free(tbuf);
6500 }
6501 }
6502
6503 if (reload)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006504 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00006505 buf_reload(buf, orig_mode);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006506
Bram Moolenaar56718732006-03-15 22:53:57 +00006507#ifdef FEAT_AUTOCMD
6508 if (buf_valid(buf))
6509 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST,
6510 buf->b_fname, buf->b_fname, FALSE, buf);
6511#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006512#ifdef FEAT_GUI
6513 /* restore this in case an autocommand has set it; it would break
6514 * 'mousefocus' */
6515 need_mouse_correct = save_mouse_correct;
6516#endif
6517
6518 return retval;
6519}
6520
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006521/*
6522 * Reload a buffer that is already loaded.
6523 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00006524 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
6525 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006526 */
6527 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00006528buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006529 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00006530 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006531{
6532 exarg_T ea;
6533 pos_T old_cursor;
6534 linenr_T old_topline;
6535 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006536 buf_T *savebuf;
6537 int saved = OK;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006538 aco_save_T aco;
6539
6540 /* set curwin/curbuf for "buf" and save some things */
6541 aucmd_prepbuf(&aco, buf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006542
6543 /* We only want to read the text from the file, not reset the syntax
6544 * highlighting, clear marks, diff status, etc. Force the fileformat
6545 * and encoding to be the same. */
6546 if (prep_exarg(&ea, buf) == OK)
6547 {
6548 old_cursor = curwin->w_cursor;
6549 old_topline = curwin->w_topline;
6550
6551 /*
6552 * To behave like when a new file is edited (matters for
6553 * BufReadPost autocommands) we first need to delete the current
6554 * buffer contents. But if reading the file fails we should keep
6555 * the old contents. Can't use memory only, the file might be
6556 * too big. Use a hidden buffer to move the buffer contents to.
6557 */
6558 if (bufempty())
6559 savebuf = NULL;
6560 else
6561 {
6562 /* Allocate a buffer without putting it in the buffer list. */
6563 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006564 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006565 {
6566 /* Open the memline. */
6567 curbuf = savebuf;
6568 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00006569 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006570 curbuf = buf;
6571 curwin->w_buffer = buf;
6572 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006573 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006574 || move_lines(buf, savebuf) == FAIL)
6575 {
6576 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6577 buf->b_fname);
6578 saved = FAIL;
6579 }
6580 }
6581
6582 if (saved == OK)
6583 {
6584 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6585#ifdef FEAT_AUTOCMD
6586 keep_filetype = TRUE; /* don't detect 'filetype' */
6587#endif
6588 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6589 (linenr_T)0,
6590 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6591 {
6592#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6593 if (!aborting())
6594#endif
6595 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006596 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006597 {
6598 /* Put the text back from the save buffer. First
6599 * delete any lines that readfile() added. */
6600 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00006601 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006602 break;
6603 (void)move_lines(savebuf, buf);
6604 }
6605 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006606 else if (buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006607 {
6608 /* Mark the buffer as unmodified and free undo info. */
6609 unchanged(buf, TRUE);
6610 u_blockfree(buf);
6611 u_clearall(buf);
6612 }
6613 }
6614 vim_free(ea.cmd);
6615
Bram Moolenaar8424a622006-04-19 21:23:36 +00006616 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006617 wipe_buffer(savebuf, FALSE);
6618
6619#ifdef FEAT_DIFF
6620 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00006621 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006622#endif
6623
6624 /* Restore the topline and cursor position and check it (lines may
6625 * have been removed). */
6626 if (old_topline > curbuf->b_ml.ml_line_count)
6627 curwin->w_topline = curbuf->b_ml.ml_line_count;
6628 else
6629 curwin->w_topline = old_topline;
6630 curwin->w_cursor = old_cursor;
6631 check_cursor();
6632 update_topline();
6633#ifdef FEAT_AUTOCMD
6634 keep_filetype = FALSE;
6635#endif
6636#ifdef FEAT_FOLDING
6637 {
6638 win_T *wp;
6639
6640 /* Update folds unless they are defined manually. */
6641 FOR_ALL_WINDOWS(wp)
6642 if (wp->w_buffer == curwin->w_buffer
6643 && !foldmethodIsManual(wp))
6644 foldUpdateAll(wp);
6645 }
6646#endif
6647 /* If the mode didn't change and 'readonly' was set, keep the old
6648 * value; the user probably used the ":view" command. But don't
6649 * reset it, might have had a read error. */
6650 if (orig_mode == curbuf->b_orig_mode)
6651 curbuf->b_p_ro |= old_ro;
6652 }
6653
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006654 /* restore curwin/curbuf and a few other things */
6655 aucmd_restbuf(&aco);
6656 /* Careful: autocommands may have made "buf" invalid! */
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006657}
6658
Bram Moolenaar071d4272004-06-13 20:20:40 +00006659/*ARGSUSED*/
6660 void
6661buf_store_time(buf, st, fname)
6662 buf_T *buf;
6663 struct stat *st;
6664 char_u *fname;
6665{
6666 buf->b_mtime = (long)st->st_mtime;
6667 buf->b_orig_size = (size_t)st->st_size;
6668#ifdef HAVE_ST_MODE
6669 buf->b_orig_mode = (int)st->st_mode;
6670#else
6671 buf->b_orig_mode = mch_getperm(fname);
6672#endif
6673}
6674
6675/*
6676 * Adjust the line with missing eol, used for the next write.
6677 * Used for do_filter(), when the input lines for the filter are deleted.
6678 */
6679 void
6680write_lnum_adjust(offset)
6681 linenr_T offset;
6682{
Bram Moolenaardf177f62005-02-22 08:39:57 +00006683 if (write_no_eol_lnum != 0) /* only if there is a missing eol */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006684 write_no_eol_lnum += offset;
6685}
6686
6687#if defined(TEMPDIRNAMES) || defined(PROTO)
6688static long temp_count = 0; /* Temp filename counter. */
6689
6690/*
6691 * Delete the temp directory and all files it contains.
6692 */
6693 void
6694vim_deltempdir()
6695{
6696 char_u **files;
6697 int file_count;
6698 int i;
6699
6700 if (vim_tempdir != NULL)
6701 {
6702 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6703 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6704 EW_DIR|EW_FILE|EW_SILENT) == OK)
6705 {
6706 for (i = 0; i < file_count; ++i)
6707 mch_remove(files[i]);
6708 FreeWild(file_count, files);
6709 }
6710 gettail(NameBuff)[-1] = NUL;
6711 (void)mch_rmdir(NameBuff);
6712
6713 vim_free(vim_tempdir);
6714 vim_tempdir = NULL;
6715 }
6716}
6717#endif
6718
6719/*
6720 * vim_tempname(): Return a unique name that can be used for a temp file.
6721 *
6722 * The temp file is NOT created.
6723 *
6724 * The returned pointer is to allocated memory.
6725 * The returned pointer is NULL if no valid name was found.
6726 */
6727/*ARGSUSED*/
6728 char_u *
6729vim_tempname(extra_char)
6730 int extra_char; /* character to use in the name instead of '?' */
6731{
6732#ifdef USE_TMPNAM
6733 char_u itmp[L_tmpnam]; /* use tmpnam() */
6734#else
6735 char_u itmp[TEMPNAMELEN];
6736#endif
6737
6738#ifdef TEMPDIRNAMES
6739 static char *(tempdirs[]) = {TEMPDIRNAMES};
6740 int i;
6741 long nr;
6742 long off;
6743# ifndef EEXIST
6744 struct stat st;
6745# endif
6746
6747 /*
6748 * This will create a directory for private use by this instance of Vim.
6749 * This is done once, and the same directory is used for all temp files.
6750 * This method avoids security problems because of symlink attacks et al.
6751 * It's also a bit faster, because we only need to check for an existing
6752 * file when creating the directory and not for each temp file.
6753 */
6754 if (vim_tempdir == NULL)
6755 {
6756 /*
6757 * Try the entries in TEMPDIRNAMES to create the temp directory.
6758 */
6759 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6760 {
6761 /* expand $TMP, leave room for "/v1100000/999999999" */
6762 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6763 if (mch_isdir(itmp)) /* directory exists */
6764 {
6765# ifdef __EMX__
6766 /* If $TMP contains a forward slash (perhaps using bash or
6767 * tcsh), don't add a backslash, use a forward slash!
6768 * Adding 2 backslashes didn't work. */
6769 if (vim_strchr(itmp, '/') != NULL)
6770 STRCAT(itmp, "/");
6771 else
6772# endif
6773 add_pathsep(itmp);
6774
6775 /* Get an arbitrary number of up to 6 digits. When it's
6776 * unlikely that it already exists it will be faster,
6777 * otherwise it doesn't matter. The use of mkdir() avoids any
6778 * security problems because of the predictable number. */
6779 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6780
6781 /* Try up to 10000 different values until we find a name that
6782 * doesn't exist. */
6783 for (off = 0; off < 10000L; ++off)
6784 {
6785 int r;
6786#if defined(UNIX) || defined(VMS)
6787 mode_t umask_save;
6788#endif
6789
6790 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6791# ifndef EEXIST
6792 /* If mkdir() does not set errno to EEXIST, check for
6793 * existing file here. There is a race condition then,
6794 * although it's fail-safe. */
6795 if (mch_stat((char *)itmp, &st) >= 0)
6796 continue;
6797# endif
6798#if defined(UNIX) || defined(VMS)
6799 /* Make sure the umask doesn't remove the executable bit.
6800 * "repl" has been reported to use "177". */
6801 umask_save = umask(077);
6802#endif
6803 r = vim_mkdir(itmp, 0700);
6804#if defined(UNIX) || defined(VMS)
6805 (void)umask(umask_save);
6806#endif
6807 if (r == 0)
6808 {
6809 char_u *buf;
6810
6811 /* Directory was created, use this name.
6812 * Expand to full path; When using the current
6813 * directory a ":cd" would confuse us. */
6814 buf = alloc((unsigned)MAXPATHL + 1);
6815 if (buf != NULL)
6816 {
6817 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6818 == FAIL)
6819 STRCPY(buf, itmp);
6820# ifdef __EMX__
6821 if (vim_strchr(buf, '/') != NULL)
6822 STRCAT(buf, "/");
6823 else
6824# endif
6825 add_pathsep(buf);
6826 vim_tempdir = vim_strsave(buf);
6827 vim_free(buf);
6828 }
6829 break;
6830 }
6831# ifdef EEXIST
6832 /* If the mkdir() didn't fail because the file/dir exists,
6833 * we probably can't create any dir here, try another
6834 * place. */
6835 if (errno != EEXIST)
6836# endif
6837 break;
6838 }
6839 if (vim_tempdir != NULL)
6840 break;
6841 }
6842 }
6843 }
6844
6845 if (vim_tempdir != NULL)
6846 {
6847 /* There is no need to check if the file exists, because we own the
6848 * directory and nobody else creates a file in it. */
6849 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6850 return vim_strsave(itmp);
6851 }
6852
6853 return NULL;
6854
6855#else /* TEMPDIRNAMES */
6856
6857# ifdef WIN3264
6858 char szTempFile[_MAX_PATH + 1];
6859 char buf4[4];
6860 char_u *retval;
6861 char_u *p;
6862
6863 STRCPY(itmp, "");
6864 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6865 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6866 strcpy(buf4, "VIM");
6867 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6868 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6869 return NULL;
6870 /* GetTempFileName() will create the file, we don't want that */
6871 (void)DeleteFile(itmp);
6872
6873 /* Backslashes in a temp file name cause problems when filtering with
6874 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6875 * didn't set 'shellslash'. */
6876 retval = vim_strsave(itmp);
6877 if (*p_shcf == '-' || p_ssl)
6878 for (p = retval; *p; ++p)
6879 if (*p == '\\')
6880 *p = '/';
6881 return retval;
6882
6883# else /* WIN3264 */
6884
6885# ifdef USE_TMPNAM
6886 /* tmpnam() will make its own name */
6887 if (*tmpnam((char *)itmp) == NUL)
6888 return NULL;
6889# else
6890 char_u *p;
6891
6892# ifdef VMS_TEMPNAM
6893 /* mktemp() is not working on VMS. It seems to be
6894 * a do-nothing function. Therefore we use tempnam().
6895 */
6896 sprintf((char *)itmp, "VIM%c", extra_char);
6897 p = (char_u *)tempnam("tmp:", (char *)itmp);
6898 if (p != NULL)
6899 {
6900 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6901 * and VIM will then be unable to find the file later */
6902 STRCPY(itmp, p);
6903 STRCAT(itmp, ".txt");
6904 free(p);
6905 }
6906 else
6907 return NULL;
6908# else
6909 STRCPY(itmp, TEMPNAME);
6910 if ((p = vim_strchr(itmp, '?')) != NULL)
6911 *p = extra_char;
6912 if (mktemp((char *)itmp) == NULL)
6913 return NULL;
6914# endif
6915# endif
6916
6917 return vim_strsave(itmp);
6918# endif /* WIN3264 */
6919#endif /* TEMPDIRNAMES */
6920}
6921
6922#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6923/*
6924 * Convert all backslashes in fname to forward slashes in-place.
6925 */
6926 void
6927forward_slash(fname)
6928 char_u *fname;
6929{
6930 char_u *p;
6931
6932 for (p = fname; *p != NUL; ++p)
6933# ifdef FEAT_MBYTE
6934 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00006935 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006936 ++p;
6937 else
6938# endif
6939 if (*p == '\\')
6940 *p = '/';
6941}
6942#endif
6943
6944
6945/*
6946 * Code for automatic commands.
6947 *
6948 * Only included when "FEAT_AUTOCMD" has been defined.
6949 */
6950
6951#if defined(FEAT_AUTOCMD) || defined(PROTO)
6952
6953/*
6954 * The autocommands are stored in a list for each event.
6955 * Autocommands for the same pattern, that are consecutive, are joined
6956 * together, to avoid having to match the pattern too often.
6957 * The result is an array of Autopat lists, which point to AutoCmd lists:
6958 *
6959 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6960 * Autopat.cmds Autopat.cmds
6961 * | |
6962 * V V
6963 * AutoCmd.next AutoCmd.next
6964 * | |
6965 * V V
6966 * AutoCmd.next NULL
6967 * |
6968 * V
6969 * NULL
6970 *
6971 * first_autopat[1] --> Autopat.next --> NULL
6972 * Autopat.cmds
6973 * |
6974 * V
6975 * AutoCmd.next
6976 * |
6977 * V
6978 * NULL
6979 * etc.
6980 *
6981 * The order of AutoCmds is important, this is the order in which they were
6982 * defined and will have to be executed.
6983 */
6984typedef struct AutoCmd
6985{
6986 char_u *cmd; /* The command to be executed (NULL
6987 when command has been removed) */
6988 char nested; /* If autocommands nest here */
6989 char last; /* last command in list */
6990#ifdef FEAT_EVAL
6991 scid_T scriptID; /* script ID where defined */
6992#endif
6993 struct AutoCmd *next; /* Next AutoCmd in list */
6994} AutoCmd;
6995
6996typedef struct AutoPat
6997{
6998 int group; /* group ID */
6999 char_u *pat; /* pattern as typed (NULL when pattern
7000 has been removed) */
7001 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00007002 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007003 char allow_dirs; /* Pattern may match whole path */
7004 char last; /* last pattern for apply_autocmds() */
7005 AutoCmd *cmds; /* list of commands to do */
7006 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007007 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007008} AutoPat;
7009
7010static struct event_name
7011{
7012 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007013 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014} event_names[] =
7015{
7016 {"BufAdd", EVENT_BUFADD},
7017 {"BufCreate", EVENT_BUFADD},
7018 {"BufDelete", EVENT_BUFDELETE},
7019 {"BufEnter", EVENT_BUFENTER},
7020 {"BufFilePost", EVENT_BUFFILEPOST},
7021 {"BufFilePre", EVENT_BUFFILEPRE},
7022 {"BufHidden", EVENT_BUFHIDDEN},
7023 {"BufLeave", EVENT_BUFLEAVE},
7024 {"BufNew", EVENT_BUFNEW},
7025 {"BufNewFile", EVENT_BUFNEWFILE},
7026 {"BufRead", EVENT_BUFREADPOST},
7027 {"BufReadCmd", EVENT_BUFREADCMD},
7028 {"BufReadPost", EVENT_BUFREADPOST},
7029 {"BufReadPre", EVENT_BUFREADPRE},
7030 {"BufUnload", EVENT_BUFUNLOAD},
7031 {"BufWinEnter", EVENT_BUFWINENTER},
7032 {"BufWinLeave", EVENT_BUFWINLEAVE},
7033 {"BufWipeout", EVENT_BUFWIPEOUT},
7034 {"BufWrite", EVENT_BUFWRITEPRE},
7035 {"BufWritePost", EVENT_BUFWRITEPOST},
7036 {"BufWritePre", EVENT_BUFWRITEPRE},
7037 {"BufWriteCmd", EVENT_BUFWRITECMD},
7038 {"CmdwinEnter", EVENT_CMDWINENTER},
7039 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007040 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007041 {"CursorHold", EVENT_CURSORHOLD},
7042 {"CursorHoldI", EVENT_CURSORHOLDI},
7043 {"CursorMoved", EVENT_CURSORMOVED},
7044 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007045 {"EncodingChanged", EVENT_ENCODINGCHANGED},
7046 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007047 {"FileAppendPost", EVENT_FILEAPPENDPOST},
7048 {"FileAppendPre", EVENT_FILEAPPENDPRE},
7049 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
7050 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00007051 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007052 {"FileChangedRO", EVENT_FILECHANGEDRO},
7053 {"FileReadPost", EVENT_FILEREADPOST},
7054 {"FileReadPre", EVENT_FILEREADPRE},
7055 {"FileReadCmd", EVENT_FILEREADCMD},
7056 {"FileType", EVENT_FILETYPE},
7057 {"FileWritePost", EVENT_FILEWRITEPOST},
7058 {"FileWritePre", EVENT_FILEWRITEPRE},
7059 {"FileWriteCmd", EVENT_FILEWRITECMD},
7060 {"FilterReadPost", EVENT_FILTERREADPOST},
7061 {"FilterReadPre", EVENT_FILTERREADPRE},
7062 {"FilterWritePost", EVENT_FILTERWRITEPOST},
7063 {"FilterWritePre", EVENT_FILTERWRITEPRE},
7064 {"FocusGained", EVENT_FOCUSGAINED},
7065 {"FocusLost", EVENT_FOCUSLOST},
7066 {"FuncUndefined", EVENT_FUNCUNDEFINED},
7067 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar265e5072006-08-29 16:13:22 +00007068 {"GUIFailed", EVENT_GUIFAILED},
Bram Moolenaar843ee412004-06-30 16:16:41 +00007069 {"InsertChange", EVENT_INSERTCHANGE},
7070 {"InsertEnter", EVENT_INSERTENTER},
7071 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00007072 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00007073 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
7074 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007075 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007076 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007077 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7078 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007079 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaar8dd1aa52007-01-16 20:33:19 +00007080 {"SourceCmd", EVENT_SOURCECMD},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007081 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007082 {"StdinReadPost", EVENT_STDINREADPOST},
7083 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007084 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007085 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007086 {"TabEnter", EVENT_TABENTER},
7087 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007088 {"TermChanged", EVENT_TERMCHANGED},
7089 {"TermResponse", EVENT_TERMRESPONSE},
7090 {"User", EVENT_USER},
7091 {"VimEnter", EVENT_VIMENTER},
7092 {"VimLeave", EVENT_VIMLEAVE},
7093 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7094 {"WinEnter", EVENT_WINENTER},
7095 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007096 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007097 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007098};
7099
7100static AutoPat *first_autopat[NUM_EVENTS] =
7101{
7102 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7103 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7104 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7105 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007106 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7107 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007108};
7109
7110/*
7111 * struct used to keep status while executing autocommands for an event.
7112 */
7113typedef struct AutoPatCmd
7114{
7115 AutoPat *curpat; /* next AutoPat to examine */
7116 AutoCmd *nextcmd; /* next AutoCmd to execute */
7117 int group; /* group being used */
7118 char_u *fname; /* fname to match with */
7119 char_u *sfname; /* sfname to match with */
7120 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007121 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007122 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7123 buf is deleted */
7124 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007125} AutoPatCmd;
7126
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007127static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007128
Bram Moolenaar071d4272004-06-13 20:20:40 +00007129/*
7130 * augroups stores a list of autocmd group names.
7131 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007132static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007133#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7134
7135/*
7136 * The ID of the current group. Group 0 is the default one.
7137 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007138static int current_augroup = AUGROUP_DEFAULT;
7139
7140static int au_need_clean = FALSE; /* need to delete marked patterns */
7141
Bram Moolenaar754b5602006-02-09 23:53:20 +00007142static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007143static void au_remove_pat __ARGS((AutoPat *ap));
7144static void au_remove_cmds __ARGS((AutoPat *ap));
7145static void au_cleanup __ARGS((void));
7146static int au_new_group __ARGS((char_u *name));
7147static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007148static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7149static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007150static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007151static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007152static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007153static 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 +00007154static char_u *getnextac __ARGS((int c, void *cookie, int indent));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007155static 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 +00007156static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7157
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007158
Bram Moolenaar754b5602006-02-09 23:53:20 +00007159static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007160static int last_group;
7161
7162/*
7163 * Show the autocommands for one AutoPat.
7164 */
7165 static void
7166show_autocmd(ap, event)
7167 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007168 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007169{
7170 AutoCmd *ac;
7171
7172 /* Check for "got_int" (here and at various places below), which is set
7173 * when "q" has been hit for the "--more--" prompt */
7174 if (got_int)
7175 return;
7176 if (ap->pat == NULL) /* pattern has been removed */
7177 return;
7178
7179 msg_putchar('\n');
7180 if (got_int)
7181 return;
7182 if (event != last_event || ap->group != last_group)
7183 {
7184 if (ap->group != AUGROUP_DEFAULT)
7185 {
7186 if (AUGROUP_NAME(ap->group) == NULL)
7187 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7188 else
7189 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7190 msg_puts((char_u *)" ");
7191 }
7192 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7193 last_event = event;
7194 last_group = ap->group;
7195 msg_putchar('\n');
7196 if (got_int)
7197 return;
7198 }
7199 msg_col = 4;
7200 msg_outtrans(ap->pat);
7201
7202 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7203 {
7204 if (ac->cmd != NULL) /* skip removed commands */
7205 {
7206 if (msg_col >= 14)
7207 msg_putchar('\n');
7208 msg_col = 14;
7209 if (got_int)
7210 return;
7211 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007212#ifdef FEAT_EVAL
7213 if (p_verbose > 0)
7214 last_set_msg(ac->scriptID);
7215#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007216 if (got_int)
7217 return;
7218 if (ac->next != NULL)
7219 {
7220 msg_putchar('\n');
7221 if (got_int)
7222 return;
7223 }
7224 }
7225 }
7226}
7227
7228/*
7229 * Mark an autocommand pattern for deletion.
7230 */
7231 static void
7232au_remove_pat(ap)
7233 AutoPat *ap;
7234{
7235 vim_free(ap->pat);
7236 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007237 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007238 au_need_clean = TRUE;
7239}
7240
7241/*
7242 * Mark all commands for a pattern for deletion.
7243 */
7244 static void
7245au_remove_cmds(ap)
7246 AutoPat *ap;
7247{
7248 AutoCmd *ac;
7249
7250 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7251 {
7252 vim_free(ac->cmd);
7253 ac->cmd = NULL;
7254 }
7255 au_need_clean = TRUE;
7256}
7257
7258/*
7259 * Cleanup autocommands and patterns that have been deleted.
7260 * This is only done when not executing autocommands.
7261 */
7262 static void
7263au_cleanup()
7264{
7265 AutoPat *ap, **prev_ap;
7266 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007267 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007268
7269 if (autocmd_busy || !au_need_clean)
7270 return;
7271
7272 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007273 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7274 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007275 {
7276 /* loop over all autocommand patterns */
7277 prev_ap = &(first_autopat[(int)event]);
7278 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7279 {
7280 /* loop over all commands for this pattern */
7281 prev_ac = &(ap->cmds);
7282 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7283 {
7284 /* remove the command if the pattern is to be deleted or when
7285 * the command has been marked for deletion */
7286 if (ap->pat == NULL || ac->cmd == NULL)
7287 {
7288 *prev_ac = ac->next;
7289 vim_free(ac->cmd);
7290 vim_free(ac);
7291 }
7292 else
7293 prev_ac = &(ac->next);
7294 }
7295
7296 /* remove the pattern if it has been marked for deletion */
7297 if (ap->pat == NULL)
7298 {
7299 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007300 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007301 vim_free(ap);
7302 }
7303 else
7304 prev_ap = &(ap->next);
7305 }
7306 }
7307
7308 au_need_clean = FALSE;
7309}
7310
7311/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007312 * Called when buffer is freed, to remove/invalidate related buffer-local
7313 * autocmds.
7314 */
7315 void
7316aubuflocal_remove(buf)
7317 buf_T *buf;
7318{
7319 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007320 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007321 AutoPatCmd *apc;
7322
7323 /* invalidate currently executing autocommands */
7324 for (apc = active_apc_list; apc; apc = apc->next)
7325 if (buf->b_fnum == apc->arg_bufnr)
7326 apc->arg_bufnr = 0;
7327
7328 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007329 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7330 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007331 /* loop over all autocommand patterns */
7332 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7333 if (ap->buflocal_nr == buf->b_fnum)
7334 {
7335 au_remove_pat(ap);
7336 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007337 {
7338 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007339 smsg((char_u *)
7340 _("auto-removing autocommand: %s <buffer=%d>"),
7341 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007342 verbose_leave();
7343 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007344 }
7345 au_cleanup();
7346}
7347
7348/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007349 * Add an autocmd group name.
7350 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7351 */
7352 static int
7353au_new_group(name)
7354 char_u *name;
7355{
7356 int i;
7357
7358 i = au_find_group(name);
7359 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
7360 {
7361 /* First try using a free entry. */
7362 for (i = 0; i < augroups.ga_len; ++i)
7363 if (AUGROUP_NAME(i) == NULL)
7364 break;
7365 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
7366 return AUGROUP_ERROR;
7367
7368 AUGROUP_NAME(i) = vim_strsave(name);
7369 if (AUGROUP_NAME(i) == NULL)
7370 return AUGROUP_ERROR;
7371 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007372 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007373 }
7374
7375 return i;
7376}
7377
7378 static void
7379au_del_group(name)
7380 char_u *name;
7381{
7382 int i;
7383
7384 i = au_find_group(name);
7385 if (i == AUGROUP_ERROR) /* the group doesn't exist */
7386 EMSG2(_("E367: No such group: \"%s\""), name);
7387 else
7388 {
7389 vim_free(AUGROUP_NAME(i));
7390 AUGROUP_NAME(i) = NULL;
7391 }
7392}
7393
7394/*
7395 * Find the ID of an autocmd group name.
7396 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7397 */
7398 static int
7399au_find_group(name)
7400 char_u *name;
7401{
7402 int i;
7403
7404 for (i = 0; i < augroups.ga_len; ++i)
7405 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
7406 return i;
7407 return AUGROUP_ERROR;
7408}
7409
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007410/*
7411 * Return TRUE if augroup "name" exists.
7412 */
7413 int
7414au_has_group(name)
7415 char_u *name;
7416{
7417 return au_find_group(name) != AUGROUP_ERROR;
7418}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007419
Bram Moolenaar071d4272004-06-13 20:20:40 +00007420/*
7421 * ":augroup {name}".
7422 */
7423 void
7424do_augroup(arg, del_group)
7425 char_u *arg;
7426 int del_group;
7427{
7428 int i;
7429
7430 if (del_group)
7431 {
7432 if (*arg == NUL)
7433 EMSG(_(e_argreq));
7434 else
7435 au_del_group(arg);
7436 }
7437 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
7438 current_augroup = AUGROUP_DEFAULT;
7439 else if (*arg) /* ":aug xxx": switch to group xxx */
7440 {
7441 i = au_new_group(arg);
7442 if (i != AUGROUP_ERROR)
7443 current_augroup = i;
7444 }
7445 else /* ":aug": list the group names */
7446 {
7447 msg_start();
7448 for (i = 0; i < augroups.ga_len; ++i)
7449 {
7450 if (AUGROUP_NAME(i) != NULL)
7451 {
7452 msg_puts(AUGROUP_NAME(i));
7453 msg_puts((char_u *)" ");
7454 }
7455 }
7456 msg_clr_eos();
7457 msg_end();
7458 }
7459}
7460
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007461#if defined(EXITFREE) || defined(PROTO)
7462 void
7463free_all_autocmds()
7464{
7465 for (current_augroup = -1; current_augroup < augroups.ga_len;
7466 ++current_augroup)
7467 do_autocmd((char_u *)"", TRUE);
7468 ga_clear_strings(&augroups);
7469}
7470#endif
7471
Bram Moolenaar071d4272004-06-13 20:20:40 +00007472/*
7473 * Return the event number for event name "start".
7474 * Return NUM_EVENTS if the event name was not found.
7475 * Return a pointer to the next event name in "end".
7476 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007477 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478event_name2nr(start, end)
7479 char_u *start;
7480 char_u **end;
7481{
7482 char_u *p;
7483 int i;
7484 int len;
7485
7486 /* the event name ends with end of line, a blank or a comma */
7487 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7488 ;
7489 for (i = 0; event_names[i].name != NULL; ++i)
7490 {
7491 len = (int)STRLEN(event_names[i].name);
7492 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7493 break;
7494 }
7495 if (*p == ',')
7496 ++p;
7497 *end = p;
7498 if (event_names[i].name == NULL)
7499 return NUM_EVENTS;
7500 return event_names[i].event;
7501}
7502
7503/*
7504 * Return the name for event "event".
7505 */
7506 static char_u *
7507event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007508 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007509{
7510 int i;
7511
7512 for (i = 0; event_names[i].name != NULL; ++i)
7513 if (event_names[i].event == event)
7514 return (char_u *)event_names[i].name;
7515 return (char_u *)"Unknown";
7516}
7517
7518/*
7519 * Scan over the events. "*" stands for all events.
7520 */
7521 static char_u *
7522find_end_event(arg, have_group)
7523 char_u *arg;
7524 int have_group; /* TRUE when group name was found */
7525{
7526 char_u *pat;
7527 char_u *p;
7528
7529 if (*arg == '*')
7530 {
7531 if (arg[1] && !vim_iswhite(arg[1]))
7532 {
7533 EMSG2(_("E215: Illegal character after *: %s"), arg);
7534 return NULL;
7535 }
7536 pat = arg + 1;
7537 }
7538 else
7539 {
7540 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7541 {
7542 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7543 {
7544 if (have_group)
7545 EMSG2(_("E216: No such event: %s"), pat);
7546 else
7547 EMSG2(_("E216: No such group or event: %s"), pat);
7548 return NULL;
7549 }
7550 }
7551 }
7552 return pat;
7553}
7554
7555/*
7556 * Return TRUE if "event" is included in 'eventignore'.
7557 */
7558 static int
7559event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007560 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007561{
7562 char_u *p = p_ei;
7563
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007564 while (*p != NUL)
7565 {
7566 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
7567 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007568 if (event_name2nr(p, &p) == event)
7569 return TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007570 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007571
7572 return FALSE;
7573}
7574
7575/*
7576 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7577 */
7578 int
7579check_ei()
7580{
7581 char_u *p = p_ei;
7582
Bram Moolenaar071d4272004-06-13 20:20:40 +00007583 while (*p)
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007584 {
7585 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
7586 {
7587 p += 3;
7588 if (*p == ',')
7589 ++p;
7590 }
7591 else if (event_name2nr(p, &p) == NUM_EVENTS)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007592 return FAIL;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007593 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007594
7595 return OK;
7596}
7597
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007598# if defined(FEAT_SYN_HL) || defined(PROTO)
7599
7600/*
7601 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7602 * buffer loaded into the window. "what" must start with a comma.
7603 * Returns the old value of 'eventignore' in allocated memory.
7604 */
7605 char_u *
7606au_event_disable(what)
7607 char *what;
7608{
7609 char_u *new_ei;
7610 char_u *save_ei;
7611
7612 save_ei = vim_strsave(p_ei);
7613 if (save_ei != NULL)
7614 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00007615 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007616 if (new_ei != NULL)
7617 {
7618 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007619 set_string_option_direct((char_u *)"ei", -1, new_ei,
7620 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007621 vim_free(new_ei);
7622 }
7623 }
7624 return save_ei;
7625}
7626
7627 void
7628au_event_restore(old_ei)
7629 char_u *old_ei;
7630{
7631 if (old_ei != NULL)
7632 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007633 set_string_option_direct((char_u *)"ei", -1, old_ei,
7634 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007635 vim_free(old_ei);
7636 }
7637}
7638# endif /* FEAT_SYN_HL */
7639
Bram Moolenaar071d4272004-06-13 20:20:40 +00007640/*
7641 * do_autocmd() -- implements the :autocmd command. Can be used in the
7642 * following ways:
7643 *
7644 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7645 * will be automatically executed for <event>
7646 * when editing a file matching <pat>, in
7647 * the current group.
7648 * :autocmd <event> <pat> Show the auto-commands associated with
7649 * <event> and <pat>.
7650 * :autocmd <event> Show the auto-commands associated with
7651 * <event>.
7652 * :autocmd Show all auto-commands.
7653 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7654 * <event> and <pat>, and add the command
7655 * <cmd>, for the current group.
7656 * :autocmd! <event> <pat> Remove all auto-commands associated with
7657 * <event> and <pat> for the current group.
7658 * :autocmd! <event> Remove all auto-commands associated with
7659 * <event> for the current group.
7660 * :autocmd! Remove ALL auto-commands for the current
7661 * group.
7662 *
7663 * Multiple events and patterns may be given separated by commas. Here are
7664 * some examples:
7665 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7666 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7667 *
7668 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00007669 *
7670 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007671 */
7672 void
7673do_autocmd(arg, forceit)
7674 char_u *arg;
7675 int forceit;
7676{
7677 char_u *pat;
7678 char_u *envpat = NULL;
7679 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007680 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007681 int need_free = FALSE;
7682 int nested = FALSE;
7683 int group;
7684
7685 /*
7686 * Check for a legal group name. If not, use AUGROUP_ALL.
7687 */
7688 group = au_get_grouparg(&arg);
7689 if (arg == NULL) /* out of memory */
7690 return;
7691
7692 /*
7693 * Scan over the events.
7694 * If we find an illegal name, return here, don't do anything.
7695 */
7696 pat = find_end_event(arg, group != AUGROUP_ALL);
7697 if (pat == NULL)
7698 return;
7699
7700 /*
7701 * Scan over the pattern. Put a NUL at the end.
7702 */
7703 pat = skipwhite(pat);
7704 cmd = pat;
7705 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7706 cmd++;
7707 if (*cmd)
7708 *cmd++ = NUL;
7709
7710 /* Expand environment variables in the pattern. Set 'shellslash', we want
7711 * forward slashes here. */
7712 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7713 {
7714#ifdef BACKSLASH_IN_FILENAME
7715 int p_ssl_save = p_ssl;
7716
7717 p_ssl = TRUE;
7718#endif
7719 envpat = expand_env_save(pat);
7720#ifdef BACKSLASH_IN_FILENAME
7721 p_ssl = p_ssl_save;
7722#endif
7723 if (envpat != NULL)
7724 pat = envpat;
7725 }
7726
7727 /*
7728 * Check for "nested" flag.
7729 */
7730 cmd = skipwhite(cmd);
7731 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7732 {
7733 nested = TRUE;
7734 cmd = skipwhite(cmd + 6);
7735 }
7736
7737 /*
7738 * Find the start of the commands.
7739 * Expand <sfile> in it.
7740 */
7741 if (*cmd != NUL)
7742 {
7743 cmd = expand_sfile(cmd);
7744 if (cmd == NULL) /* some error */
7745 return;
7746 need_free = TRUE;
7747 }
7748
7749 /*
7750 * Print header when showing autocommands.
7751 */
7752 if (!forceit && *cmd == NUL)
7753 {
7754 /* Highlight title */
7755 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7756 }
7757
7758 /*
7759 * Loop over the events.
7760 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007761 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007762 last_group = AUGROUP_ERROR; /* for listing the group name */
7763 if (*arg == '*' || *arg == NUL)
7764 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00007765 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7766 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007767 if (do_autocmd_event(event, pat,
7768 nested, cmd, forceit, group) == FAIL)
7769 break;
7770 }
7771 else
7772 {
7773 while (*arg && !vim_iswhite(*arg))
7774 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7775 nested, cmd, forceit, group) == FAIL)
7776 break;
7777 }
7778
7779 if (need_free)
7780 vim_free(cmd);
7781 vim_free(envpat);
7782}
7783
7784/*
7785 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7786 * The "argp" argument is advanced to the following argument.
7787 *
7788 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7789 */
7790 static int
7791au_get_grouparg(argp)
7792 char_u **argp;
7793{
7794 char_u *group_name;
7795 char_u *p;
7796 char_u *arg = *argp;
7797 int group = AUGROUP_ALL;
7798
7799 p = skiptowhite(arg);
7800 if (p > arg)
7801 {
7802 group_name = vim_strnsave(arg, (int)(p - arg));
7803 if (group_name == NULL) /* out of memory */
7804 return AUGROUP_ERROR;
7805 group = au_find_group(group_name);
7806 if (group == AUGROUP_ERROR)
7807 group = AUGROUP_ALL; /* no match, use all groups */
7808 else
7809 *argp = skipwhite(p); /* match, skip over group name */
7810 vim_free(group_name);
7811 }
7812 return group;
7813}
7814
7815/*
7816 * do_autocmd() for one event.
7817 * If *pat == NUL do for all patterns.
7818 * If *cmd == NUL show entries.
7819 * If forceit == TRUE delete entries.
7820 * If group is not AUGROUP_ALL, only use this group.
7821 */
7822 static int
7823do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007824 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007825 char_u *pat;
7826 int nested;
7827 char_u *cmd;
7828 int forceit;
7829 int group;
7830{
7831 AutoPat *ap;
7832 AutoPat **prev_ap;
7833 AutoCmd *ac;
7834 AutoCmd **prev_ac;
7835 int brace_level;
7836 char_u *endpat;
7837 int findgroup;
7838 int allgroups;
7839 int patlen;
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00007840 int is_buflocal;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007841 int buflocal_nr;
7842 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007843
7844 if (group == AUGROUP_ALL)
7845 findgroup = current_augroup;
7846 else
7847 findgroup = group;
7848 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7849
7850 /*
7851 * Show or delete all patterns for an event.
7852 */
7853 if (*pat == NUL)
7854 {
7855 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7856 {
7857 if (forceit) /* delete the AutoPat, if it's in the current group */
7858 {
7859 if (ap->group == findgroup)
7860 au_remove_pat(ap);
7861 }
7862 else if (group == AUGROUP_ALL || ap->group == group)
7863 show_autocmd(ap, event);
7864 }
7865 }
7866
7867 /*
7868 * Loop through all the specified patterns.
7869 */
7870 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7871 {
7872 /*
7873 * Find end of the pattern.
7874 * Watch out for a comma in braces, like "*.\{obj,o\}".
7875 */
7876 brace_level = 0;
7877 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7878 || endpat[-1] == '\\'); ++endpat)
7879 {
7880 if (*endpat == '{')
7881 brace_level++;
7882 else if (*endpat == '}')
7883 brace_level--;
7884 }
7885 if (pat == endpat) /* ignore single comma */
7886 continue;
7887 patlen = (int)(endpat - pat);
7888
7889 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007890 * detect special <buflocal[=X]> buffer-local patterns
7891 */
7892 is_buflocal = FALSE;
7893 buflocal_nr = 0;
7894
7895 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
7896 && pat[patlen - 1] == '>')
7897 {
7898 /* Error will be printed only for addition. printing and removing
7899 * will proceed silently. */
7900 is_buflocal = TRUE;
7901 if (patlen == 8)
7902 buflocal_nr = curbuf->b_fnum;
7903 else if (patlen > 9 && pat[7] == '=')
7904 {
7905 /* <buffer=abuf> */
7906 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
7907 buflocal_nr = autocmd_bufnr;
7908 /* <buffer=123> */
7909 else if (skipdigits(pat + 8) == pat + patlen - 1)
7910 buflocal_nr = atoi((char *)pat + 8);
7911 }
7912 }
7913
7914 if (is_buflocal)
7915 {
7916 /* normalize pat into standard "<buffer>#N" form */
7917 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
7918 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007919 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007920 }
7921
7922 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007923 * Find AutoPat entries with this pattern.
7924 */
7925 prev_ap = &first_autopat[(int)event];
7926 while ((ap = *prev_ap) != NULL)
7927 {
7928 if (ap->pat != NULL)
7929 {
7930 /* Accept a pattern when:
7931 * - a group was specified and it's that group, or a group was
7932 * not specified and it's the current group, or a group was
7933 * not specified and we are listing
7934 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007935 * - the pattern matches.
7936 * For <buffer[=X]>, this condition works because we normalize
7937 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007938 */
7939 if ((allgroups || ap->group == findgroup)
7940 && ap->patlen == patlen
7941 && STRNCMP(pat, ap->pat, patlen) == 0)
7942 {
7943 /*
7944 * Remove existing autocommands.
7945 * If adding any new autocmd's for this AutoPat, don't
7946 * delete the pattern from the autopat list, append to
7947 * this list.
7948 */
7949 if (forceit)
7950 {
7951 if (*cmd != NUL && ap->next == NULL)
7952 {
7953 au_remove_cmds(ap);
7954 break;
7955 }
7956 au_remove_pat(ap);
7957 }
7958
7959 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007960 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00007961 */
7962 else if (*cmd == NUL)
7963 show_autocmd(ap, event);
7964
7965 /*
7966 * Add autocmd to this autopat, if it's the last one.
7967 */
7968 else if (ap->next == NULL)
7969 break;
7970 }
7971 }
7972 prev_ap = &ap->next;
7973 }
7974
7975 /*
7976 * Add a new command.
7977 */
7978 if (*cmd != NUL)
7979 {
7980 /*
7981 * If the pattern we want to add a command to does appear at the
7982 * end of the list (or not is not in the list at all), add the
7983 * pattern at the end of the list.
7984 */
7985 if (ap == NULL)
7986 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007987 /* refuse to add buffer-local ap if buffer number is invalid */
7988 if (is_buflocal && (buflocal_nr == 0
7989 || buflist_findnr(buflocal_nr) == NULL))
7990 {
7991 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
7992 buflocal_nr);
7993 return FAIL;
7994 }
7995
Bram Moolenaar071d4272004-06-13 20:20:40 +00007996 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7997 if (ap == NULL)
7998 return FAIL;
7999 ap->pat = vim_strnsave(pat, patlen);
8000 ap->patlen = patlen;
8001 if (ap->pat == NULL)
8002 {
8003 vim_free(ap);
8004 return FAIL;
8005 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008006
8007 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008008 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008009 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008010 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008011 }
8012 else
8013 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00008014 char_u *reg_pat;
8015
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008016 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008017 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008018 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008019 if (reg_pat != NULL)
8020 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00008021 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00008022 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008023 {
8024 vim_free(ap->pat);
8025 vim_free(ap);
8026 return FAIL;
8027 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008028 }
8029 ap->cmds = NULL;
8030 *prev_ap = ap;
8031 ap->next = NULL;
8032 if (group == AUGROUP_ALL)
8033 ap->group = current_augroup;
8034 else
8035 ap->group = group;
8036 }
8037
8038 /*
8039 * Add the autocmd at the end of the AutoCmd list.
8040 */
8041 prev_ac = &(ap->cmds);
8042 while ((ac = *prev_ac) != NULL)
8043 prev_ac = &ac->next;
8044 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
8045 if (ac == NULL)
8046 return FAIL;
8047 ac->cmd = vim_strsave(cmd);
8048#ifdef FEAT_EVAL
8049 ac->scriptID = current_SID;
8050#endif
8051 if (ac->cmd == NULL)
8052 {
8053 vim_free(ac);
8054 return FAIL;
8055 }
8056 ac->next = NULL;
8057 *prev_ac = ac;
8058 ac->nested = nested;
8059 }
8060 }
8061
8062 au_cleanup(); /* may really delete removed patterns/commands now */
8063 return OK;
8064}
8065
8066/*
8067 * Implementation of ":doautocmd [group] event [fname]".
8068 * Return OK for success, FAIL for failure;
8069 */
8070 int
8071do_doautocmd(arg, do_msg)
8072 char_u *arg;
8073 int do_msg; /* give message for no matching autocmds? */
8074{
8075 char_u *fname;
8076 int nothing_done = TRUE;
8077 int group;
8078
8079 /*
8080 * Check for a legal group name. If not, use AUGROUP_ALL.
8081 */
8082 group = au_get_grouparg(&arg);
8083 if (arg == NULL) /* out of memory */
8084 return FAIL;
8085
8086 if (*arg == '*')
8087 {
8088 EMSG(_("E217: Can't execute autocommands for ALL events"));
8089 return FAIL;
8090 }
8091
8092 /*
8093 * Scan over the events.
8094 * If we find an illegal name, return here, don't do anything.
8095 */
8096 fname = find_end_event(arg, group != AUGROUP_ALL);
8097 if (fname == NULL)
8098 return FAIL;
8099
8100 fname = skipwhite(fname);
8101
8102 /*
8103 * Loop over the events.
8104 */
8105 while (*arg && !vim_iswhite(*arg))
8106 if (apply_autocmds_group(event_name2nr(arg, &arg),
8107 fname, NULL, TRUE, group, curbuf, NULL))
8108 nothing_done = FALSE;
8109
8110 if (nothing_done && do_msg)
8111 MSG(_("No matching autocommands"));
8112
8113#ifdef FEAT_EVAL
8114 return aborting() ? FAIL : OK;
8115#else
8116 return OK;
8117#endif
8118}
8119
8120/*
8121 * ":doautoall": execute autocommands for each loaded buffer.
8122 */
8123 void
8124ex_doautoall(eap)
8125 exarg_T *eap;
8126{
8127 int retval;
8128 aco_save_T aco;
8129 buf_T *buf;
8130
8131 /*
8132 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8133 * equal to curbuf, but for some buffers there may not be a window.
8134 * So we change the buffer for the current window for a moment. This
8135 * gives problems when the autocommands make changes to the list of
8136 * buffers or windows...
8137 */
8138 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8139 {
8140 if (curbuf->b_ml.ml_mfp != NULL)
8141 {
8142 /* find a window for this buffer and save some values */
8143 aucmd_prepbuf(&aco, buf);
8144
8145 /* execute the autocommands for this buffer */
8146 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaareeefcc72007-05-01 21:21:21 +00008147
8148 /* Execute the modeline settings, but don't set window-local
8149 * options if we are using the current window for another buffer. */
8150 do_modelines(aco.save_curwin == NULL ? OPT_NOWIN : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008151
8152 /* restore the current window */
8153 aucmd_restbuf(&aco);
8154
8155 /* stop if there is some error or buffer was deleted */
8156 if (retval == FAIL || !buf_valid(buf))
8157 break;
8158 }
8159 }
8160
8161 check_cursor(); /* just in case lines got deleted */
8162}
8163
8164/*
8165 * Prepare for executing autocommands for (hidden) buffer "buf".
8166 * Search a window for the current buffer. Save the cursor position and
8167 * screen offset.
8168 * Set "curbuf" and "curwin" to match "buf".
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008169 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008170 */
8171 void
8172aucmd_prepbuf(aco, buf)
8173 aco_save_T *aco; /* structure to save values in */
8174 buf_T *buf; /* new curbuf */
8175{
8176 win_T *win;
8177
8178 aco->new_curbuf = buf;
8179
8180 /* Find a window that is for the new buffer */
8181 if (buf == curbuf) /* be quick when buf is curbuf */
8182 win = curwin;
8183 else
8184#ifdef FEAT_WINDOWS
8185 for (win = firstwin; win != NULL; win = win->w_next)
8186 if (win->w_buffer == buf)
8187 break;
8188#else
8189 win = NULL;
8190#endif
8191
8192 /*
8193 * Prefer to use an existing window for the buffer, it has the least side
8194 * effects (esp. if "buf" is curbuf).
8195 * Otherwise, use curwin for "buf". It might make some items in the
8196 * window invalid. At least save the cursor and topline.
8197 */
8198 if (win != NULL)
8199 {
8200 /* there is a window for "buf", make it the curwin */
8201 aco->save_curwin = curwin;
8202 curwin = win;
8203 aco->save_buf = win->w_buffer;
8204 aco->new_curwin = win;
8205 }
8206 else
8207 {
8208 /* there is no window for "buf", use curwin */
8209 aco->save_curwin = NULL;
8210 aco->save_buf = curbuf;
8211 --curbuf->b_nwindows;
8212 curwin->w_buffer = buf;
8213 ++buf->b_nwindows;
8214
8215 /* save cursor and topline, set them to safe values */
8216 aco->save_cursor = curwin->w_cursor;
8217 curwin->w_cursor.lnum = 1;
8218 curwin->w_cursor.col = 0;
8219 aco->save_topline = curwin->w_topline;
8220 curwin->w_topline = 1;
8221#ifdef FEAT_DIFF
8222 aco->save_topfill = curwin->w_topfill;
8223 curwin->w_topfill = 0;
8224#endif
8225 }
8226
8227 curbuf = buf;
8228}
8229
8230/*
8231 * Cleanup after executing autocommands for a (hidden) buffer.
8232 * Restore the window as it was (if possible).
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00008233 * When FEAT_AUTOCMD is not defined another version is used, see below.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008234 */
8235 void
8236aucmd_restbuf(aco)
8237 aco_save_T *aco; /* structure holding saved values */
8238{
8239 if (aco->save_curwin != NULL)
8240 {
8241 /* restore curwin */
8242#ifdef FEAT_WINDOWS
8243 if (win_valid(aco->save_curwin))
8244#endif
8245 {
8246 /* restore the buffer which was previously edited by curwin, if
8247 * it's still the same window and it's valid */
8248 if (curwin == aco->new_curwin
8249 && buf_valid(aco->save_buf)
8250 && aco->save_buf->b_ml.ml_mfp != NULL)
8251 {
8252 --curbuf->b_nwindows;
8253 curbuf = aco->save_buf;
8254 curwin->w_buffer = curbuf;
8255 ++curbuf->b_nwindows;
8256 }
8257
8258 curwin = aco->save_curwin;
8259 curbuf = curwin->w_buffer;
8260 }
8261 }
8262 else
8263 {
8264 /* restore buffer for curwin if it still exists and is loaded */
8265 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
8266 {
8267 --curbuf->b_nwindows;
8268 curbuf = aco->save_buf;
8269 curwin->w_buffer = curbuf;
8270 ++curbuf->b_nwindows;
8271 curwin->w_cursor = aco->save_cursor;
8272 check_cursor();
8273 /* check topline < line_count, in case lines got deleted */
8274 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
8275 {
8276 curwin->w_topline = aco->save_topline;
8277#ifdef FEAT_DIFF
8278 curwin->w_topfill = aco->save_topfill;
8279#endif
8280 }
8281 else
8282 {
8283 curwin->w_topline = curbuf->b_ml.ml_line_count;
8284#ifdef FEAT_DIFF
8285 curwin->w_topfill = 0;
8286#endif
8287 }
8288 }
8289 }
8290}
8291
8292static int autocmd_nested = FALSE;
8293
8294/*
8295 * Execute autocommands for "event" and file name "fname".
8296 * Return TRUE if some commands were executed.
8297 */
8298 int
8299apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008300 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008301 char_u *fname; /* NULL or empty means use actual file name */
8302 char_u *fname_io; /* fname to use for <afile> on cmdline */
8303 int force; /* when TRUE, ignore autocmd_busy */
8304 buf_T *buf; /* buffer for <abuf> */
8305{
8306 return apply_autocmds_group(event, fname, fname_io, force,
8307 AUGROUP_ALL, buf, NULL);
8308}
8309
8310/*
8311 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
8312 * setting v:filearg.
8313 */
8314 static int
8315apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008316 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008317 char_u *fname;
8318 char_u *fname_io;
8319 int force;
8320 buf_T *buf;
8321 exarg_T *eap;
8322{
8323 return apply_autocmds_group(event, fname, fname_io, force,
8324 AUGROUP_ALL, buf, eap);
8325}
8326
8327/*
8328 * Like apply_autocmds(), but handles the caller's retval. If the script
8329 * processing is being aborted or if retval is FAIL when inside a try
8330 * conditional, no autocommands are executed. If otherwise the autocommands
8331 * cause the script to be aborted, retval is set to FAIL.
8332 */
8333 int
8334apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008335 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008336 char_u *fname; /* NULL or empty means use actual file name */
8337 char_u *fname_io; /* fname to use for <afile> on cmdline */
8338 int force; /* when TRUE, ignore autocmd_busy */
8339 buf_T *buf; /* buffer for <abuf> */
8340 int *retval; /* pointer to caller's retval */
8341{
8342 int did_cmd;
8343
Bram Moolenaar1e015462005-09-25 22:16:38 +00008344#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008345 if (should_abort(*retval))
8346 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00008347#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008348
8349 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
8350 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008351 if (did_cmd
8352#ifdef FEAT_EVAL
8353 && aborting()
8354#endif
8355 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008356 *retval = FAIL;
8357 return did_cmd;
8358}
8359
Bram Moolenaard35f9712005-12-18 22:02:33 +00008360/*
8361 * Return TRUE when there is a CursorHold autocommand defined.
8362 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008363 int
8364has_cursorhold()
8365{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008366 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
8367 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008368}
Bram Moolenaard35f9712005-12-18 22:02:33 +00008369
8370/*
8371 * Return TRUE if the CursorHold event can be triggered.
8372 */
8373 int
8374trigger_cursorhold()
8375{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008376 int state;
8377
Bram Moolenaard29a9ee2006-09-14 09:07:34 +00008378 if (!did_cursorhold && has_cursorhold() && !Recording
8379#ifdef FEAT_INS_EXPAND
8380 && !ins_compl_active()
8381#endif
8382 )
Bram Moolenaar754b5602006-02-09 23:53:20 +00008383 {
8384 state = get_real_state();
8385 if (state == NORMAL_BUSY || (state & INSERT) != 0)
8386 return TRUE;
8387 }
8388 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00008389}
Bram Moolenaar754b5602006-02-09 23:53:20 +00008390
8391/*
8392 * Return TRUE when there is a CursorMoved autocommand defined.
8393 */
8394 int
8395has_cursormoved()
8396{
8397 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
8398}
8399
8400/*
8401 * Return TRUE when there is a CursorMovedI autocommand defined.
8402 */
8403 int
8404has_cursormovedI()
8405{
8406 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
8407}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008408
8409 static int
8410apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008411 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008412 char_u *fname; /* NULL or empty means use actual file name */
8413 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
8414 use fname */
8415 int force; /* when TRUE, ignore autocmd_busy */
8416 int group; /* group ID, or AUGROUP_ALL */
8417 buf_T *buf; /* buffer for <abuf> */
8418 exarg_T *eap; /* command arguments */
8419{
8420 char_u *sfname = NULL; /* short file name */
8421 char_u *tail;
8422 int save_changed;
8423 buf_T *old_curbuf;
8424 int retval = FALSE;
8425 char_u *save_sourcing_name;
8426 linenr_T save_sourcing_lnum;
8427 char_u *save_autocmd_fname;
8428 int save_autocmd_bufnr;
8429 char_u *save_autocmd_match;
8430 int save_autocmd_busy;
8431 int save_autocmd_nested;
8432 static int nesting = 0;
8433 AutoPatCmd patcmd;
8434 AutoPat *ap;
8435#ifdef FEAT_EVAL
8436 scid_T save_current_SID;
8437 void *save_funccalp;
8438 char_u *save_cmdarg;
8439 long save_cmdbang;
8440#endif
8441 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00008442#ifdef FEAT_PROFILE
8443 proftime_T wait_time;
8444#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008445
8446 /*
8447 * Quickly return if there are no autocommands for this event or
8448 * autocommands are blocked.
8449 */
8450 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008451 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008452
8453 /*
8454 * When autocommands are busy, new autocommands are only executed when
8455 * explicitly enabled with the "nested" flag.
8456 */
8457 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008458 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008459
8460#ifdef FEAT_EVAL
8461 /*
Bram Moolenaar7263a772007-05-10 17:35:54 +00008462 * Quickly return when immediately aborting on error, or when an interrupt
Bram Moolenaar071d4272004-06-13 20:20:40 +00008463 * occurred or an exception was thrown but not caught.
8464 */
8465 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008466 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008467#endif
8468
8469 /*
8470 * FileChangedShell never nests, because it can create an endless loop.
8471 */
Bram Moolenaar56718732006-03-15 22:53:57 +00008472 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
8473 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008474 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008475
8476 /*
8477 * Ignore events in 'eventignore'.
8478 */
8479 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008480 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008481
8482 /*
8483 * Allow nesting of autocommands, but restrict the depth, because it's
8484 * possible to create an endless loop.
8485 */
8486 if (nesting == 10)
8487 {
8488 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008489 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008490 }
8491
8492 /*
8493 * Check if these autocommands are disabled. Used when doing ":all" or
8494 * ":ball".
8495 */
8496 if ( (autocmd_no_enter
8497 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
8498 || (autocmd_no_leave
8499 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008500 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008501
8502 /*
8503 * Save the autocmd_* variables and info about the current buffer.
8504 */
8505 save_autocmd_fname = autocmd_fname;
8506 save_autocmd_bufnr = autocmd_bufnr;
8507 save_autocmd_match = autocmd_match;
8508 save_autocmd_busy = autocmd_busy;
8509 save_autocmd_nested = autocmd_nested;
8510 save_changed = curbuf->b_changed;
8511 old_curbuf = curbuf;
8512
8513 /*
8514 * Set the file name to be used for <afile>.
8515 */
8516 if (fname_io == NULL)
8517 {
8518 if (fname != NULL && *fname != NUL)
8519 autocmd_fname = fname;
8520 else if (buf != NULL)
8521 autocmd_fname = buf->b_fname;
8522 else
8523 autocmd_fname = NULL;
8524 }
8525 else
8526 autocmd_fname = fname_io;
8527
8528 /*
8529 * Set the buffer number to be used for <abuf>.
8530 */
8531 if (buf == NULL)
8532 autocmd_bufnr = 0;
8533 else
8534 autocmd_bufnr = buf->b_fnum;
8535
8536 /*
8537 * When the file name is NULL or empty, use the file name of buffer "buf".
8538 * Always use the full path of the file name to match with, in case
8539 * "allow_dirs" is set.
8540 */
8541 if (fname == NULL || *fname == NUL)
8542 {
8543 if (buf == NULL)
8544 fname = NULL;
8545 else
8546 {
8547#ifdef FEAT_SYN_HL
8548 if (event == EVENT_SYNTAX)
8549 fname = buf->b_p_syn;
8550 else
8551#endif
8552 if (event == EVENT_FILETYPE)
8553 fname = buf->b_p_ft;
8554 else
8555 {
8556 if (buf->b_sfname != NULL)
8557 sfname = vim_strsave(buf->b_sfname);
8558 fname = buf->b_ffname;
8559 }
8560 }
8561 if (fname == NULL)
8562 fname = (char_u *)"";
8563 fname = vim_strsave(fname); /* make a copy, so we can change it */
8564 }
8565 else
8566 {
8567 sfname = vim_strsave(fname);
Bram Moolenaar7c626922005-02-07 22:01:03 +00008568 /* Don't try expanding FileType, Syntax, WindowID or QuickFixCmd* */
8569 if (event == EVENT_FILETYPE
8570 || event == EVENT_SYNTAX
8571 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00008572 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00008573 || event == EVENT_QUICKFIXCMDPRE
8574 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008575 fname = vim_strsave(fname);
8576 else
8577 fname = FullName_save(fname, FALSE);
8578 }
8579 if (fname == NULL) /* out of memory */
8580 {
8581 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008582 retval = FALSE;
8583 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008584 }
8585
8586#ifdef BACKSLASH_IN_FILENAME
8587 /*
8588 * Replace all backslashes with forward slashes. This makes the
8589 * autocommand patterns portable between Unix and MS-DOS.
8590 */
8591 if (sfname != NULL)
8592 forward_slash(sfname);
8593 forward_slash(fname);
8594#endif
8595
8596#ifdef VMS
8597 /* remove version for correct match */
8598 if (sfname != NULL)
8599 vms_remove_version(sfname);
8600 vms_remove_version(fname);
8601#endif
8602
8603 /*
8604 * Set the name to be used for <amatch>.
8605 */
8606 autocmd_match = fname;
8607
8608
8609 /* Don't redraw while doing auto commands. */
8610 ++RedrawingDisabled;
8611 save_sourcing_name = sourcing_name;
8612 sourcing_name = NULL; /* don't free this one */
8613 save_sourcing_lnum = sourcing_lnum;
8614 sourcing_lnum = 0; /* no line number here */
8615
8616#ifdef FEAT_EVAL
8617 save_current_SID = current_SID;
8618
Bram Moolenaar05159a02005-02-26 23:04:13 +00008619# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00008620 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00008621 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
8622# endif
8623
Bram Moolenaar071d4272004-06-13 20:20:40 +00008624 /* Don't use local function variables, if called from a function */
8625 save_funccalp = save_funccal();
8626#endif
8627
8628 /*
8629 * When starting to execute autocommands, save the search patterns.
8630 */
8631 if (!autocmd_busy)
8632 {
8633 save_search_patterns();
8634 saveRedobuff();
8635 did_filetype = keep_filetype;
8636 }
8637
8638 /*
8639 * Note that we are applying autocmds. Some commands need to know.
8640 */
8641 autocmd_busy = TRUE;
8642 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
8643 ++nesting; /* see matching decrement below */
8644
8645 /* Remember that FileType was triggered. Used for did_filetype(). */
8646 if (event == EVENT_FILETYPE)
8647 did_filetype = TRUE;
8648
8649 tail = gettail(fname);
8650
8651 /* Find first autocommand that matches */
8652 patcmd.curpat = first_autopat[(int)event];
8653 patcmd.nextcmd = NULL;
8654 patcmd.group = group;
8655 patcmd.fname = fname;
8656 patcmd.sfname = sfname;
8657 patcmd.tail = tail;
8658 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008659 patcmd.arg_bufnr = autocmd_bufnr;
8660 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008661 auto_next_pat(&patcmd, FALSE);
8662
8663 /* found one, start executing the autocommands */
8664 if (patcmd.curpat != NULL)
8665 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008666 /* add to active_apc_list */
8667 patcmd.next = active_apc_list;
8668 active_apc_list = &patcmd;
8669
Bram Moolenaar071d4272004-06-13 20:20:40 +00008670#ifdef FEAT_EVAL
8671 /* set v:cmdarg (only when there is a matching pattern) */
8672 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
8673 if (eap != NULL)
8674 {
8675 save_cmdarg = set_cmdarg(eap, NULL);
8676 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
8677 }
8678 else
8679 save_cmdarg = NULL; /* avoid gcc warning */
8680#endif
8681 retval = TRUE;
8682 /* mark the last pattern, to avoid an endless loop when more patterns
8683 * are added when executing autocommands */
8684 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8685 ap->last = FALSE;
8686 ap->last = TRUE;
8687 check_lnums(TRUE); /* make sure cursor and topline are valid */
8688 do_cmdline(NULL, getnextac, (void *)&patcmd,
8689 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8690#ifdef FEAT_EVAL
8691 if (eap != NULL)
8692 {
8693 (void)set_cmdarg(NULL, save_cmdarg);
8694 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8695 }
8696#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008697 /* delete from active_apc_list */
8698 if (active_apc_list == &patcmd) /* just in case */
8699 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008700 }
8701
8702 --RedrawingDisabled;
8703 autocmd_busy = save_autocmd_busy;
8704 filechangeshell_busy = FALSE;
8705 autocmd_nested = save_autocmd_nested;
8706 vim_free(sourcing_name);
8707 sourcing_name = save_sourcing_name;
8708 sourcing_lnum = save_sourcing_lnum;
8709 autocmd_fname = save_autocmd_fname;
8710 autocmd_bufnr = save_autocmd_bufnr;
8711 autocmd_match = save_autocmd_match;
8712#ifdef FEAT_EVAL
8713 current_SID = save_current_SID;
8714 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00008715# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00008716 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00008717 prof_child_exit(&wait_time);
8718# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008719#endif
8720 vim_free(fname);
8721 vim_free(sfname);
8722 --nesting; /* see matching increment above */
8723
8724 /*
8725 * When stopping to execute autocommands, restore the search patterns and
8726 * the redo buffer.
8727 */
8728 if (!autocmd_busy)
8729 {
8730 restore_search_patterns();
8731 restoreRedobuff();
8732 did_filetype = FALSE;
8733 }
8734
8735 /*
8736 * Some events don't set or reset the Changed flag.
8737 * Check if still in the same buffer!
8738 */
8739 if (curbuf == old_curbuf
8740 && (event == EVENT_BUFREADPOST
8741 || event == EVENT_BUFWRITEPOST
8742 || event == EVENT_FILEAPPENDPOST
8743 || event == EVENT_VIMLEAVE
8744 || event == EVENT_VIMLEAVEPRE))
8745 {
8746#ifdef FEAT_TITLE
8747 if (curbuf->b_changed != save_changed)
8748 need_maketitle = TRUE;
8749#endif
8750 curbuf->b_changed = save_changed;
8751 }
8752
8753 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008754
8755BYPASS_AU:
8756 /* When wiping out a buffer make sure all its buffer-local autocommands
8757 * are deleted. */
8758 if (event == EVENT_BUFWIPEOUT && buf != NULL)
8759 aubuflocal_remove(buf);
8760
Bram Moolenaar071d4272004-06-13 20:20:40 +00008761 return retval;
8762}
8763
8764/*
8765 * Find next autocommand pattern that matches.
8766 */
8767 static void
8768auto_next_pat(apc, stop_at_last)
8769 AutoPatCmd *apc;
8770 int stop_at_last; /* stop when 'last' flag is set */
8771{
8772 AutoPat *ap;
8773 AutoCmd *cp;
8774 char_u *name;
8775 char *s;
8776
8777 vim_free(sourcing_name);
8778 sourcing_name = NULL;
8779
8780 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8781 {
8782 apc->curpat = NULL;
8783
8784 /* only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008785 * the group matches. For buffer-local autocommands only check the
8786 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008787 if (ap->pat != NULL && ap->cmds != NULL
8788 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8789 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008790 /* execution-condition */
8791 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008792 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
8793 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008794 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008795 {
8796 name = event_nr2name(apc->event);
8797 s = _("%s Auto commands for \"%s\"");
8798 sourcing_name = alloc((unsigned)(STRLEN(s)
8799 + STRLEN(name) + ap->patlen + 1));
8800 if (sourcing_name != NULL)
8801 {
8802 sprintf((char *)sourcing_name, s,
8803 (char *)name, (char *)ap->pat);
8804 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008805 {
8806 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008807 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008808 verbose_leave();
8809 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810 }
8811
8812 apc->curpat = ap;
8813 apc->nextcmd = ap->cmds;
8814 /* mark last command */
8815 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8816 cp->last = FALSE;
8817 cp->last = TRUE;
8818 }
8819 line_breakcheck();
8820 if (apc->curpat != NULL) /* found a match */
8821 break;
8822 }
8823 if (stop_at_last && ap->last)
8824 break;
8825 }
8826}
8827
8828/*
8829 * Get next autocommand command.
8830 * Called by do_cmdline() to get the next line for ":if".
8831 * Returns allocated string, or NULL for end of autocommands.
8832 */
8833/* ARGSUSED */
8834 static char_u *
8835getnextac(c, cookie, indent)
8836 int c; /* not used */
8837 void *cookie;
8838 int indent; /* not used */
8839{
8840 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8841 char_u *retval;
8842 AutoCmd *ac;
8843
8844 /* Can be called again after returning the last line. */
8845 if (acp->curpat == NULL)
8846 return NULL;
8847
8848 /* repeat until we find an autocommand to execute */
8849 for (;;)
8850 {
8851 /* skip removed commands */
8852 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8853 if (acp->nextcmd->last)
8854 acp->nextcmd = NULL;
8855 else
8856 acp->nextcmd = acp->nextcmd->next;
8857
8858 if (acp->nextcmd != NULL)
8859 break;
8860
8861 /* at end of commands, find next pattern that matches */
8862 if (acp->curpat->last)
8863 acp->curpat = NULL;
8864 else
8865 acp->curpat = acp->curpat->next;
8866 if (acp->curpat != NULL)
8867 auto_next_pat(acp, TRUE);
8868 if (acp->curpat == NULL)
8869 return NULL;
8870 }
8871
8872 ac = acp->nextcmd;
8873
8874 if (p_verbose >= 9)
8875 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008876 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008877 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008878 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008879 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008880 }
8881 retval = vim_strsave(ac->cmd);
8882 autocmd_nested = ac->nested;
8883#ifdef FEAT_EVAL
8884 current_SID = ac->scriptID;
8885#endif
8886 if (ac->last)
8887 acp->nextcmd = NULL;
8888 else
8889 acp->nextcmd = ac->next;
8890 return retval;
8891}
8892
8893/*
8894 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008895 * To account for buffer-local autocommands, function needs to know
8896 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008897 */
8898 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008899has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008900 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008901 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008902 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008903{
8904 AutoPat *ap;
8905 char_u *fname;
8906 char_u *tail = gettail(sfname);
8907 int retval = FALSE;
8908
8909 fname = FullName_save(sfname, FALSE);
8910 if (fname == NULL)
8911 return FALSE;
8912
8913#ifdef BACKSLASH_IN_FILENAME
8914 /*
8915 * Replace all backslashes with forward slashes. This makes the
8916 * autocommand patterns portable between Unix and MS-DOS.
8917 */
8918 sfname = vim_strsave(sfname);
8919 if (sfname != NULL)
8920 forward_slash(sfname);
8921 forward_slash(fname);
8922#endif
8923
8924 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8925 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008926 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008927 ? match_file_pat(NULL, ap->reg_prog,
8928 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00008929 : buf != NULL && ap->buflocal_nr == buf->b_fnum
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008930 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008931 {
8932 retval = TRUE;
8933 break;
8934 }
8935
8936 vim_free(fname);
8937#ifdef BACKSLASH_IN_FILENAME
8938 vim_free(sfname);
8939#endif
8940
8941 return retval;
8942}
8943
8944#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8945/*
8946 * Function given to ExpandGeneric() to obtain the list of autocommand group
8947 * names.
8948 */
8949/*ARGSUSED*/
8950 char_u *
8951get_augroup_name(xp, idx)
8952 expand_T *xp;
8953 int idx;
8954{
8955 if (idx == augroups.ga_len) /* add "END" add the end */
8956 return (char_u *)"END";
8957 if (idx >= augroups.ga_len) /* end of list */
8958 return NULL;
8959 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8960 return (char_u *)"";
8961 return AUGROUP_NAME(idx); /* return a name */
8962}
8963
8964static int include_groups = FALSE;
8965
8966 char_u *
8967set_context_in_autocmd(xp, arg, doautocmd)
8968 expand_T *xp;
8969 char_u *arg;
8970 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8971{
8972 char_u *p;
8973 int group;
8974
8975 /* check for a group name, skip it if present */
8976 include_groups = FALSE;
8977 p = arg;
8978 group = au_get_grouparg(&arg);
8979 if (group == AUGROUP_ERROR)
8980 return NULL;
8981 /* If there only is a group name that's what we expand. */
8982 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8983 {
8984 arg = p;
8985 group = AUGROUP_ALL;
8986 }
8987
8988 /* skip over event name */
8989 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8990 if (*p == ',')
8991 arg = p + 1;
8992 if (*p == NUL)
8993 {
8994 if (group == AUGROUP_ALL)
8995 include_groups = TRUE;
8996 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8997 xp->xp_pattern = arg;
8998 return NULL;
8999 }
9000
9001 /* skip over pattern */
9002 arg = skipwhite(p);
9003 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
9004 arg++;
9005 if (*arg)
9006 return arg; /* expand (next) command */
9007
9008 if (doautocmd)
9009 xp->xp_context = EXPAND_FILES; /* expand file names */
9010 else
9011 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
9012 return NULL;
9013}
9014
9015/*
9016 * Function given to ExpandGeneric() to obtain the list of event names.
9017 */
9018/*ARGSUSED*/
9019 char_u *
9020get_event_name(xp, idx)
9021 expand_T *xp;
9022 int idx;
9023{
9024 if (idx < augroups.ga_len) /* First list group names, if wanted */
9025 {
9026 if (!include_groups || AUGROUP_NAME(idx) == NULL)
9027 return (char_u *)""; /* skip deleted entries */
9028 return AUGROUP_NAME(idx); /* return a name */
9029 }
9030 return (char_u *)event_names[idx - augroups.ga_len].name;
9031}
9032
9033#endif /* FEAT_CMDL_COMPL */
9034
9035/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009036 * Return TRUE if autocmd is supported.
9037 */
9038 int
9039autocmd_supported(name)
9040 char_u *name;
9041{
9042 char_u *p;
9043
9044 return (event_name2nr(name, &p) != NUM_EVENTS);
9045}
9046
9047/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00009048 * Return TRUE if an autocommand is defined for a group, event and
9049 * pattern: The group can be omitted to accept any group. "event" and "pattern"
9050 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
9051 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
9052 * Used for:
9053 * exists("#Group") or
9054 * exists("#Group#Event") or
9055 * exists("#Group#Event#pat") or
9056 * exists("#Event") or
9057 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00009058 */
9059 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00009060au_exists(arg)
9061 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009062{
Bram Moolenaar195d6352005-12-19 22:08:24 +00009063 char_u *arg_save;
9064 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009065 char_u *event_name;
9066 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00009067 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009068 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009069 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00009070 int group;
9071 int retval = FALSE;
9072
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009073 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009074 arg_save = vim_strsave(arg);
9075 if (arg_save == NULL)
9076 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00009077 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00009078 if (p != NULL)
9079 *p++ = NUL;
9080
9081 /* First, look for an autocmd group name */
9082 group = au_find_group(arg_save);
9083 if (group == AUGROUP_ERROR)
9084 {
9085 /* Didn't match a group name, assume the first argument is an event. */
9086 group = AUGROUP_ALL;
9087 event_name = arg_save;
9088 }
9089 else
9090 {
9091 if (p == NULL)
9092 {
9093 /* "Group": group name is present and it's recognized */
9094 retval = TRUE;
9095 goto theend;
9096 }
9097
9098 /* Must be "Group#Event" or "Group#Event#pat". */
9099 event_name = p;
9100 p = vim_strchr(event_name, '#');
9101 if (p != NULL)
9102 *p++ = NUL; /* "Group#Event#pat" */
9103 }
9104
9105 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009106
9107 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009108 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009109
9110 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009111 if (event == NUM_EVENTS)
9112 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009113
9114 /* Find the first autocommand for this event.
9115 * If there isn't any, return FALSE;
9116 * If there is one and no pattern given, return TRUE; */
9117 ap = first_autopat[(int)event];
9118 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009119 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009120 if (pattern == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009121 {
9122 retval = TRUE;
9123 goto theend;
9124 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009125
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009126 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9127 /* for pattern "<buffer=N>, fnamecmp() will work fine */
9128 if (STRICMP(pattern, "<buffer>") == 0)
9129 buflocal_buf = curbuf;
9130
Bram Moolenaar071d4272004-06-13 20:20:40 +00009131 /* Check if there is an autocommand with the given pattern. */
9132 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009133 /* only use a pattern when it has not been removed and has commands. */
9134 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009135 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00009136 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009137 && (buflocal_buf == NULL
9138 ? fnamecmp(ap->pat, pattern) == 0
9139 : ap->buflocal_nr == buflocal_buf->b_fnum))
Bram Moolenaar195d6352005-12-19 22:08:24 +00009140 {
9141 retval = TRUE;
9142 break;
9143 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009144
Bram Moolenaar195d6352005-12-19 22:08:24 +00009145theend:
9146 vim_free(arg_save);
9147 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009148}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009149
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009150#else /* FEAT_AUTOCMD */
9151
9152/*
9153 * Prepare for executing commands for (hidden) buffer "buf".
9154 * This is the non-autocommand version, it simply saves "curbuf" and sets
9155 * "curbuf" and "curwin" to match "buf".
9156 */
9157 void
9158aucmd_prepbuf(aco, buf)
9159 aco_save_T *aco; /* structure to save values in */
9160 buf_T *buf; /* new curbuf */
9161{
9162 aco->save_buf = buf;
9163 curbuf = buf;
9164 curwin->w_buffer = buf;
9165}
9166
9167/*
9168 * Restore after executing commands for a (hidden) buffer.
9169 * This is the non-autocommand version.
9170 */
9171 void
9172aucmd_restbuf(aco)
9173 aco_save_T *aco; /* structure holding saved values */
9174{
9175 curbuf = aco->save_buf;
9176 curwin->w_buffer = curbuf;
9177}
9178
Bram Moolenaar071d4272004-06-13 20:20:40 +00009179#endif /* FEAT_AUTOCMD */
9180
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00009181
Bram Moolenaar071d4272004-06-13 20:20:40 +00009182#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
9183/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00009184 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
9185 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
9186 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009187 * Used for autocommands and 'wildignore'.
9188 * Returns TRUE if there is a match, FALSE otherwise.
9189 */
9190 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00009191match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009192 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00009193 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009194 char_u *fname; /* full path of file name */
9195 char_u *sfname; /* short file name or NULL */
9196 char_u *tail; /* tail of path */
9197 int allow_dirs; /* allow matching with dir */
9198{
9199 regmatch_T regmatch;
9200 int result = FALSE;
9201#ifdef FEAT_OSFILETYPE
9202 int no_pattern = FALSE; /* TRUE if check is filetype only */
9203 char_u *type_start;
9204 char_u c;
9205 int match = FALSE;
9206#endif
9207
9208#ifdef CASE_INSENSITIVE_FILENAME
9209 regmatch.rm_ic = TRUE; /* Always ignore case */
9210#else
9211 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
9212#endif
9213#ifdef FEAT_OSFILETYPE
9214 if (*pattern == '<')
9215 {
9216 /* There is a filetype condition specified with this pattern.
9217 * Check the filetype matches first. If not, don't bother with the
9218 * pattern (set regprog to NULL).
9219 * Always use magic for the regexp.
9220 */
9221
9222 for (type_start = pattern + 1; (c = *pattern); pattern++)
9223 {
9224 if ((c == ';' || c == '>') && match == FALSE)
9225 {
9226 *pattern = NUL; /* Terminate the string */
9227 match = mch_check_filetype(fname, type_start);
9228 *pattern = c; /* Restore the terminator */
9229 type_start = pattern + 1;
9230 }
9231 if (c == '>')
9232 break;
9233 }
9234
9235 /* (c should never be NUL, but check anyway) */
9236 if (match == FALSE || c == NUL)
9237 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
9238 else if (*pattern == NUL)
9239 {
9240 regmatch.regprog = NULL; /* Vim will try to free regprog later */
9241 no_pattern = TRUE; /* Always matches - don't check pat. */
9242 }
9243 else
9244 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
9245 }
9246 else
9247#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00009248 {
9249 if (prog != NULL)
9250 regmatch.regprog = prog;
9251 else
9252 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
9253 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009254
9255 /*
9256 * Try for a match with the pattern with:
9257 * 1. the full file name, when the pattern has a '/'.
9258 * 2. the short file name, when the pattern has a '/'.
9259 * 3. the tail of the file name, when the pattern has no '/'.
9260 */
9261 if (
9262#ifdef FEAT_OSFILETYPE
9263 /* If the check is for a filetype only and we don't care
9264 * about the path then skip all the regexp stuff.
9265 */
9266 no_pattern ||
9267#endif
9268 (regmatch.regprog != NULL
9269 && ((allow_dirs
9270 && (vim_regexec(&regmatch, fname, (colnr_T)0)
9271 || (sfname != NULL
9272 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
9273 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
9274 result = TRUE;
9275
Bram Moolenaar748bf032005-02-02 23:04:36 +00009276 if (prog == NULL)
9277 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009278 return result;
9279}
9280#endif
9281
9282#if defined(FEAT_WILDIGN) || defined(PROTO)
9283/*
9284 * Return TRUE if a file matches with a pattern in "list".
9285 * "list" is a comma-separated list of patterns, like 'wildignore'.
9286 * "sfname" is the short file name or NULL, "ffname" the long file name.
9287 */
9288 int
9289match_file_list(list, sfname, ffname)
9290 char_u *list;
9291 char_u *sfname;
9292 char_u *ffname;
9293{
9294 char_u buf[100];
9295 char_u *tail;
9296 char_u *regpat;
9297 char allow_dirs;
9298 int match;
9299 char_u *p;
9300
9301 tail = gettail(sfname);
9302
9303 /* try all patterns in 'wildignore' */
9304 p = list;
9305 while (*p)
9306 {
9307 copy_option_part(&p, buf, 100, ",");
9308 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
9309 if (regpat == NULL)
9310 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00009311 match = match_file_pat(regpat, NULL, ffname, sfname,
9312 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009313 vim_free(regpat);
9314 if (match)
9315 return TRUE;
9316 }
9317 return FALSE;
9318}
9319#endif
9320
9321/*
9322 * Convert the given pattern "pat" which has shell style wildcards in it, into
9323 * a regular expression, and return the result in allocated memory. If there
9324 * is a directory path separator to be matched, then TRUE is put in
9325 * allow_dirs, otherwise FALSE is put there -- webb.
9326 * Handle backslashes before special characters, like "\*" and "\ ".
9327 *
9328 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
9329 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
9330 *
9331 * Returns NULL when out of memory.
9332 */
9333/*ARGSUSED*/
9334 char_u *
9335file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
9336 char_u *pat;
9337 char_u *pat_end; /* first char after pattern or NULL */
9338 char *allow_dirs; /* Result passed back out in here */
9339 int no_bslash; /* Don't use a backward slash as pathsep */
9340{
9341 int size;
9342 char_u *endp;
9343 char_u *reg_pat;
9344 char_u *p;
9345 int i;
9346 int nested = 0;
9347 int add_dollar = TRUE;
9348#ifdef FEAT_OSFILETYPE
9349 int check_length = 0;
9350#endif
9351
9352 if (allow_dirs != NULL)
9353 *allow_dirs = FALSE;
9354 if (pat_end == NULL)
9355 pat_end = pat + STRLEN(pat);
9356
9357#ifdef FEAT_OSFILETYPE
9358 /* Find out how much of the string is the filetype check */
9359 if (*pat == '<')
9360 {
9361 /* Count chars until the next '>' */
9362 for (p = pat + 1; p < pat_end && *p != '>'; p++)
9363 ;
9364 if (p < pat_end)
9365 {
9366 /* Pattern is of the form <.*>.* */
9367 check_length = p - pat + 1;
9368 if (p + 1 >= pat_end)
9369 {
9370 /* The 'pattern' is a filetype check ONLY */
9371 reg_pat = (char_u *)alloc(check_length + 1);
9372 if (reg_pat != NULL)
9373 {
9374 mch_memmove(reg_pat, pat, (size_t)check_length);
9375 reg_pat[check_length] = NUL;
9376 }
9377 return reg_pat;
9378 }
9379 }
9380 /* else: there was no closing '>' - assume it was a normal pattern */
9381
9382 }
9383 pat += check_length;
9384 size = 2 + check_length;
9385#else
9386 size = 2; /* '^' at start, '$' at end */
9387#endif
9388
9389 for (p = pat; p < pat_end; p++)
9390 {
9391 switch (*p)
9392 {
9393 case '*':
9394 case '.':
9395 case ',':
9396 case '{':
9397 case '}':
9398 case '~':
9399 size += 2; /* extra backslash */
9400 break;
9401#ifdef BACKSLASH_IN_FILENAME
9402 case '\\':
9403 case '/':
9404 size += 4; /* could become "[\/]" */
9405 break;
9406#endif
9407 default:
9408 size++;
9409# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009410 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009411 {
9412 ++p;
9413 ++size;
9414 }
9415# endif
9416 break;
9417 }
9418 }
9419 reg_pat = alloc(size + 1);
9420 if (reg_pat == NULL)
9421 return NULL;
9422
9423#ifdef FEAT_OSFILETYPE
9424 /* Copy the type check in to the start. */
9425 if (check_length)
9426 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
9427 i = check_length;
9428#else
9429 i = 0;
9430#endif
9431
9432 if (pat[0] == '*')
9433 while (pat[0] == '*' && pat < pat_end - 1)
9434 pat++;
9435 else
9436 reg_pat[i++] = '^';
9437 endp = pat_end - 1;
9438 if (*endp == '*')
9439 {
9440 while (endp - pat > 0 && *endp == '*')
9441 endp--;
9442 add_dollar = FALSE;
9443 }
9444 for (p = pat; *p && nested >= 0 && p <= endp; p++)
9445 {
9446 switch (*p)
9447 {
9448 case '*':
9449 reg_pat[i++] = '.';
9450 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +00009451 while (p[1] == '*') /* "**" matches like "*" */
9452 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009453 break;
9454 case '.':
9455#ifdef RISCOS
9456 if (allow_dirs != NULL)
9457 *allow_dirs = TRUE;
9458 /* FALLTHROUGH */
9459#endif
9460 case '~':
9461 reg_pat[i++] = '\\';
9462 reg_pat[i++] = *p;
9463 break;
9464 case '?':
9465#ifdef RISCOS
9466 case '#':
9467#endif
9468 reg_pat[i++] = '.';
9469 break;
9470 case '\\':
9471 if (p[1] == NUL)
9472 break;
9473#ifdef BACKSLASH_IN_FILENAME
9474 if (!no_bslash)
9475 {
9476 /* translate:
9477 * "\x" to "\\x" e.g., "dir\file"
9478 * "\*" to "\\.*" e.g., "dir\*.c"
9479 * "\?" to "\\." e.g., "dir\??.c"
9480 * "\+" to "\+" e.g., "fileX\+.c"
9481 */
9482 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
9483 && p[1] != '+')
9484 {
9485 reg_pat[i++] = '[';
9486 reg_pat[i++] = '\\';
9487 reg_pat[i++] = '/';
9488 reg_pat[i++] = ']';
9489 if (allow_dirs != NULL)
9490 *allow_dirs = TRUE;
9491 break;
9492 }
9493 }
9494#endif
9495 if (*++p == '?'
9496#ifdef BACKSLASH_IN_FILENAME
9497 && no_bslash
9498#endif
9499 )
9500 reg_pat[i++] = '?';
9501 else
9502 if (*p == ',')
9503 reg_pat[i++] = ',';
9504 else
9505 {
9506 if (allow_dirs != NULL && vim_ispathsep(*p)
9507#ifdef BACKSLASH_IN_FILENAME
9508 && (!no_bslash || *p != '\\')
9509#endif
9510 )
9511 *allow_dirs = TRUE;
9512 reg_pat[i++] = '\\';
9513 reg_pat[i++] = *p;
9514 }
9515 break;
9516#ifdef BACKSLASH_IN_FILENAME
9517 case '/':
9518 reg_pat[i++] = '[';
9519 reg_pat[i++] = '\\';
9520 reg_pat[i++] = '/';
9521 reg_pat[i++] = ']';
9522 if (allow_dirs != NULL)
9523 *allow_dirs = TRUE;
9524 break;
9525#endif
9526 case '{':
9527 reg_pat[i++] = '\\';
9528 reg_pat[i++] = '(';
9529 nested++;
9530 break;
9531 case '}':
9532 reg_pat[i++] = '\\';
9533 reg_pat[i++] = ')';
9534 --nested;
9535 break;
9536 case ',':
9537 if (nested)
9538 {
9539 reg_pat[i++] = '\\';
9540 reg_pat[i++] = '|';
9541 }
9542 else
9543 reg_pat[i++] = ',';
9544 break;
9545 default:
9546# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009547 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009548 reg_pat[i++] = *p++;
9549 else
9550# endif
9551 if (allow_dirs != NULL && vim_ispathsep(*p))
9552 *allow_dirs = TRUE;
9553 reg_pat[i++] = *p;
9554 break;
9555 }
9556 }
9557 if (add_dollar)
9558 reg_pat[i++] = '$';
9559 reg_pat[i] = NUL;
9560 if (nested != 0)
9561 {
9562 if (nested < 0)
9563 EMSG(_("E219: Missing {."));
9564 else
9565 EMSG(_("E220: Missing }."));
9566 vim_free(reg_pat);
9567 reg_pat = NULL;
9568 }
9569 return reg_pat;
9570}