blob: ce3e2a043d85a470d11fbc6ada7e875fbc8024b5 [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)
15# include <io.h> /* for lseek(), must be before vim.h */
16#endif
17
18#if defined __EMX__
19# include <io.h> /* for mktemp(), CJW 1997-12-03 */
20#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
47#ifdef FEAT_MBYTE
48static char_u *next_fenc __ARGS((char_u **pp));
49# ifdef FEAT_EVAL
50static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));
51# endif
52#endif
53#ifdef FEAT_VIMINFO
54static void check_marks_read __ARGS((void));
55#endif
56#ifdef FEAT_CRYPT
57static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));
58#endif
59#ifdef UNIX
60static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
61#endif
Bram Moolenaar2d3f4892006-01-20 23:02:51 +000062static int set_rw_fname __ARGS((char_u *fname, char_u *sfname));
Bram Moolenaar071d4272004-06-13 20:20:40 +000063static int msg_add_fileformat __ARGS((int eol_type));
Bram Moolenaar071d4272004-06-13 20:20:40 +000064static void msg_add_eol __ARGS((void));
65static int check_mtime __ARGS((buf_T *buf, struct stat *s));
66static int time_differs __ARGS((long t1, long t2));
67#ifdef FEAT_AUTOCMD
68static int apply_autocmds_exarg __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap));
69#endif
70
71#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
72# define HAS_BW_FLAGS
73# define FIO_LATIN1 0x01 /* convert Latin1 */
74# define FIO_UTF8 0x02 /* convert UTF-8 */
75# define FIO_UCS2 0x04 /* convert UCS-2 */
76# define FIO_UCS4 0x08 /* convert UCS-4 */
77# define FIO_UTF16 0x10 /* convert UTF-16 */
78# ifdef WIN3264
79# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
80# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
81# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
82# endif
83# ifdef MACOS_X
84# define FIO_MACROMAN 0x20 /* convert MacRoman */
85# endif
86# define FIO_ENDIAN_L 0x80 /* little endian */
87# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
88# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
89# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
90# define FIO_ALL -1 /* allow all formats */
91#endif
92
93/* When converting, a read() or write() may leave some bytes to be converted
94 * for the next call. The value is guessed... */
95#define CONV_RESTLEN 30
96
97/* We have to guess how much a sequence of bytes may expand when converting
98 * with iconv() to be able to allocate a buffer. */
99#define ICONV_MULT 8
100
101/*
102 * Structure to pass arguments from buf_write() to buf_write_bytes().
103 */
104struct bw_info
105{
106 int bw_fd; /* file descriptor */
107 char_u *bw_buf; /* buffer with data to be written */
108 int bw_len; /* lenght of data */
109#ifdef HAS_BW_FLAGS
110 int bw_flags; /* FIO_ flags */
111#endif
112#ifdef FEAT_MBYTE
113 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
114 int bw_restlen; /* nr of bytes in bw_rest[] */
115 int bw_first; /* first write call */
116 char_u *bw_conv_buf; /* buffer for writing converted chars */
117 int bw_conv_buflen; /* size of bw_conv_buf */
118 int bw_conv_error; /* set for conversion error */
119# ifdef USE_ICONV
120 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
121# endif
122#endif
123};
124
125static int buf_write_bytes __ARGS((struct bw_info *ip));
126
127#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000128static linenr_T readfile_linenr __ARGS((linenr_T linecnt, char_u *p, char_u *endp));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000129static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
130static int same_encoding __ARGS((char_u *a, char_u *b));
131static int get_fio_flags __ARGS((char_u *ptr));
132static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
133static int make_bom __ARGS((char_u *buf, char_u *name));
134# ifdef WIN3264
135static int get_win_fio_flags __ARGS((char_u *ptr));
136# endif
137# ifdef MACOS_X
138static int get_mac_fio_flags __ARGS((char_u *ptr));
139# endif
140#endif
141static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
142
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000143
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144 void
145filemess(buf, name, s, attr)
146 buf_T *buf;
147 char_u *name;
148 char_u *s;
149 int attr;
150{
151 int msg_scroll_save;
152
153 if (msg_silent != 0)
154 return;
155 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
156 /* If it's extremely long, truncate it. */
157 if (STRLEN(IObuff) > IOSIZE - 80)
158 IObuff[IOSIZE - 80] = NUL;
159 STRCAT(IObuff, s);
160 /*
161 * For the first message may have to start a new line.
162 * For further ones overwrite the previous one, reset msg_scroll before
163 * calling filemess().
164 */
165 msg_scroll_save = msg_scroll;
166 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
167 msg_scroll = FALSE;
168 if (!msg_scroll) /* wait a bit when overwriting an error msg */
169 check_for_delay(FALSE);
170 msg_start();
171 msg_scroll = msg_scroll_save;
172 msg_scrolled_ign = TRUE;
173 /* may truncate the message to avoid a hit-return prompt */
174 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
175 msg_clr_eos();
176 out_flush();
177 msg_scrolled_ign = FALSE;
178}
179
180/*
181 * Read lines from file "fname" into the buffer after line "from".
182 *
183 * 1. We allocate blocks with lalloc, as big as possible.
184 * 2. Each block is filled with characters from the file with a single read().
185 * 3. The lines are inserted in the buffer with ml_append().
186 *
187 * (caller must check that fname != NULL, unless READ_STDIN is used)
188 *
189 * "lines_to_skip" is the number of lines that must be skipped
190 * "lines_to_read" is the number of lines that are appended
191 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
192 *
193 * flags:
194 * READ_NEW starting to edit a new buffer
195 * READ_FILTER reading filter output
196 * READ_STDIN read from stdin instead of a file
197 * READ_BUFFER read from curbuf instead of a file (converting after reading
198 * stdin)
199 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
200 *
201 * return FAIL for failure, OK otherwise
202 */
203 int
204readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
205 char_u *fname;
206 char_u *sfname;
207 linenr_T from;
208 linenr_T lines_to_skip;
209 linenr_T lines_to_read;
210 exarg_T *eap; /* can be NULL! */
211 int flags;
212{
213 int fd = 0;
214 int newfile = (flags & READ_NEW);
215 int check_readonly;
216 int filtering = (flags & READ_FILTER);
217 int read_stdin = (flags & READ_STDIN);
218 int read_buffer = (flags & READ_BUFFER);
219 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
220 colnr_T read_buf_col = 0; /* next char to read from this line */
221 char_u c;
222 linenr_T lnum = from;
223 char_u *ptr = NULL; /* pointer into read buffer */
224 char_u *buffer = NULL; /* read buffer */
225 char_u *new_buffer = NULL; /* init to shut up gcc */
226 char_u *line_start = NULL; /* init to shut up gcc */
227 int wasempty; /* buffer was empty before reading */
228 colnr_T len;
229 long size = 0;
230 char_u *p;
231 long filesize = 0;
232 int skip_read = FALSE;
233#ifdef FEAT_CRYPT
234 char_u *cryptkey = NULL;
235#endif
236 int split = 0; /* number of split lines */
237#define UNKNOWN 0x0fffffff /* file size is unknown */
238 linenr_T linecnt;
239 int error = FALSE; /* errors encountered */
240 int ff_error = EOL_UNKNOWN; /* file format with errors */
241 long linerest = 0; /* remaining chars in line */
242#ifdef UNIX
243 int perm = 0;
244 int swap_mode = -1; /* protection bits for swap file */
245#else
246 int perm;
247#endif
248 int fileformat = 0; /* end-of-line format */
249 int keep_fileformat = FALSE;
250 struct stat st;
251 int file_readonly;
252 linenr_T skip_count = 0;
253 linenr_T read_count = 0;
254 int msg_save = msg_scroll;
255 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
256 * last read was missing the eol */
257 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
258 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
259 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
260 int file_rewind = FALSE;
261#ifdef FEAT_MBYTE
262 int can_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000263 linenr_T conv_error = 0; /* line nr with conversion error */
264 linenr_T illegal_byte = 0; /* line nr with illegal byte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
266 in destination encoding */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000267 int bad_char_behavior = BAD_REPLACE;
268 /* BAD_KEEP, BAD_DROP or character to
269 * replace with */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000270 char_u *tmpname = NULL; /* name of 'charconvert' output file */
271 int fio_flags = 0;
272 char_u *fenc; /* fileencoding to use */
273 int fenc_alloced; /* fenc_next is in allocated memory */
274 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
275 int advance_fenc = FALSE;
276 long real_size = 0;
277# ifdef USE_ICONV
278 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
279# ifdef FEAT_EVAL
280 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
281 'charconvert' next */
282# endif
283# endif
284 int converted = FALSE; /* TRUE if conversion done */
285 int notconverted = FALSE; /* TRUE if conversion wanted but it
286 wasn't possible */
287 char_u conv_rest[CONV_RESTLEN];
288 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
289#endif
290
Bram Moolenaar071d4272004-06-13 20:20:40 +0000291 write_no_eol_lnum = 0; /* in case it was set by the previous read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000292
293 /*
294 * If there is no file name yet, use the one for the read file.
295 * BF_NOTEDITED is set to reflect this.
296 * Don't do this for a read from a filter.
297 * Only do this when 'cpoptions' contains the 'f' flag.
298 */
299 if (curbuf->b_ffname == NULL
300 && !filtering
301 && fname != NULL
302 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
303 && !(flags & READ_DUMMY))
304 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +0000305 if (set_rw_fname(fname, sfname) == FAIL)
306 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000307 }
308
Bram Moolenaardf177f62005-02-22 08:39:57 +0000309 /* After reading a file the cursor line changes but we don't want to
310 * display the line. */
311 ex_no_reprint = TRUE;
312
Bram Moolenaar071d4272004-06-13 20:20:40 +0000313 /*
314 * For Unix: Use the short file name whenever possible.
315 * Avoids problems with networks and when directory names are changed.
316 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
317 * another directory, which we don't detect.
318 */
319 if (sfname == NULL)
320 sfname = fname;
321#if defined(UNIX) || defined(__EMX__)
322 fname = sfname;
323#endif
324
325#ifdef FEAT_AUTOCMD
326 /*
327 * The BufReadCmd and FileReadCmd events intercept the reading process by
328 * executing the associated commands instead.
329 */
330 if (!filtering && !read_stdin && !read_buffer)
331 {
332 pos_T pos;
333
334 pos = curbuf->b_op_start;
335
336 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
337 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
338 curbuf->b_op_start.col = 0;
339
340 if (newfile)
341 {
342 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
343 FALSE, curbuf, eap))
344#ifdef FEAT_EVAL
345 return aborting() ? FAIL : OK;
346#else
347 return OK;
348#endif
349 }
350 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
351 FALSE, NULL, eap))
352#ifdef FEAT_EVAL
353 return aborting() ? FAIL : OK;
354#else
355 return OK;
356#endif
357
358 curbuf->b_op_start = pos;
359 }
360#endif
361
362 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
363 msg_scroll = FALSE; /* overwrite previous file message */
364 else
365 msg_scroll = TRUE; /* don't overwrite previous file message */
366
367 /*
368 * If the name ends in a path separator, we can't open it. Check here,
369 * because reading the file may actually work, but then creating the swap
370 * file may destroy it! Reported on MS-DOS and Win 95.
371 * If the name is too long we might crash further on, quit here.
372 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000373 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000374 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000375 p = fname + STRLEN(fname);
376 if (after_pathsep(fname, p) || STRLEN(fname) >= MAXPATHL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000377 {
378 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
379 msg_end();
380 msg_scroll = msg_save;
381 return FAIL;
382 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 }
384
385#ifdef UNIX
386 /*
387 * On Unix it is possible to read a directory, so we have to
388 * check for it before the mch_open().
389 */
390 if (!read_stdin && !read_buffer)
391 {
392 perm = mch_getperm(fname);
393 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
394# ifdef S_ISFIFO
395 && !S_ISFIFO(perm) /* ... or fifo */
396# endif
397# ifdef S_ISSOCK
398 && !S_ISSOCK(perm) /* ... or socket */
399# endif
400 )
401 {
402 if (S_ISDIR(perm))
403 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
404 else
405 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
406 msg_end();
407 msg_scroll = msg_save;
408 return FAIL;
409 }
410 }
411#endif
412
413 /* set default 'fileformat' */
414 if (newfile)
415 {
416 if (eap != NULL && eap->force_ff != 0)
417 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
418 else if (*p_ffs != NUL)
419 set_fileformat(default_fileformat(), OPT_LOCAL);
420 }
421
422 /* set or reset 'binary' */
423 if (eap != NULL && eap->force_bin != 0)
424 {
425 int oldval = curbuf->b_p_bin;
426
427 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
428 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
429 }
430
431 /*
432 * When opening a new file we take the readonly flag from the file.
433 * Default is r/w, can be set to r/o below.
434 * Don't reset it when in readonly mode
435 * Only set/reset b_p_ro when BF_CHECK_RO is set.
436 */
437 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000438 if (check_readonly && !readonlymode)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000439 curbuf->b_p_ro = FALSE;
440
441 if (newfile && !read_stdin && !read_buffer)
442 {
443 /* Remember time of file.
444 * For RISCOS, also remember the filetype.
445 */
446 if (mch_stat((char *)fname, &st) >= 0)
447 {
448 buf_store_time(curbuf, &st, fname);
449 curbuf->b_mtime_read = curbuf->b_mtime;
450
451#if defined(RISCOS) && defined(FEAT_OSFILETYPE)
452 /* Read the filetype into the buffer local filetype option. */
453 mch_read_filetype(fname);
454#endif
455#ifdef UNIX
456 /*
457 * Use the protection bits of the original file for the swap file.
458 * This makes it possible for others to read the name of the
459 * edited file from the swapfile, but only if they can read the
460 * edited file.
461 * Remove the "write" and "execute" bits for group and others
462 * (they must not write the swapfile).
463 * Add the "read" and "write" bits for the user, otherwise we may
464 * not be able to write to the file ourselves.
465 * Setting the bits is done below, after creating the swap file.
466 */
467 swap_mode = (st.st_mode & 0644) | 0600;
468#endif
469#ifdef FEAT_CW_EDITOR
470 /* Get the FSSpec on MacOS
471 * TODO: Update it properly when the buffer name changes
472 */
473 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
474#endif
475#ifdef VMS
476 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000477 curbuf->b_fab_rat = st.st_fab_rat;
478 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000479#endif
480 }
481 else
482 {
483 curbuf->b_mtime = 0;
484 curbuf->b_mtime_read = 0;
485 curbuf->b_orig_size = 0;
486 curbuf->b_orig_mode = 0;
487 }
488
489 /* Reset the "new file" flag. It will be set again below when the
490 * file doesn't exist. */
491 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
492 }
493
494/*
495 * for UNIX: check readonly with perm and mch_access()
496 * for RISCOS: same as Unix, otherwise file gets re-datestamped!
497 * for MSDOS and Amiga: check readonly by trying to open the file for writing
498 */
499 file_readonly = FALSE;
500 if (read_stdin)
501 {
502#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
503 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
504 setmode(0, O_BINARY);
505#endif
506 }
507 else if (!read_buffer)
508 {
509#ifdef USE_MCH_ACCESS
510 if (
511# ifdef UNIX
512 !(perm & 0222) ||
513# endif
514 mch_access((char *)fname, W_OK))
515 file_readonly = TRUE;
516 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
517#else
518 if (!newfile
519 || readonlymode
520 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
521 {
522 file_readonly = TRUE;
523 /* try to open ro */
524 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
525 }
526#endif
527 }
528
529 if (fd < 0) /* cannot open at all */
530 {
531#ifndef UNIX
532 int isdir_f;
533#endif
534 msg_scroll = msg_save;
535#ifndef UNIX
536 /*
537 * On MSDOS and Amiga we can't open a directory, check here.
538 */
539 isdir_f = (mch_isdir(fname));
540 perm = mch_getperm(fname); /* check if the file exists */
541 if (isdir_f)
542 {
543 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
544 curbuf->b_p_ro = TRUE; /* must use "w!" now */
545 }
546 else
547#endif
548 if (newfile)
549 {
550 if (perm < 0)
551 {
552 /*
553 * Set the 'new-file' flag, so that when the file has
554 * been created by someone else, a ":w" will complain.
555 */
556 curbuf->b_flags |= BF_NEW;
557
558 /* Create a swap file now, so that other Vims are warned
559 * that we are editing this file. Don't do this for a
560 * "nofile" or "nowrite" buffer type. */
561#ifdef FEAT_QUICKFIX
562 if (!bt_dontwrite(curbuf))
563#endif
564 check_need_swap(newfile);
Bram Moolenaar5b962cf2005-12-12 21:58:40 +0000565 if (dir_of_file_exists(fname))
566 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
567 else
568 filemess(curbuf, sfname,
569 (char_u *)_("[New DIRECTORY]"), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570#ifdef FEAT_VIMINFO
571 /* Even though this is a new file, it might have been
572 * edited before and deleted. Get the old marks. */
573 check_marks_read();
574#endif
575#ifdef FEAT_MBYTE
576 if (eap != NULL && eap->force_enc != 0)
577 {
578 /* set forced 'fileencoding' */
579 fenc = enc_canonize(eap->cmd + eap->force_enc);
580 if (fenc != NULL)
581 set_string_option_direct((char_u *)"fenc", -1,
582 fenc, OPT_FREE|OPT_LOCAL);
583 vim_free(fenc);
584 }
585#endif
586#ifdef FEAT_AUTOCMD
587 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
588 FALSE, curbuf, eap);
589#endif
590 /* remember the current fileformat */
591 save_file_ff(curbuf);
592
593#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
594 if (aborting()) /* autocmds may abort script processing */
595 return FAIL;
596#endif
597 return OK; /* a new file is not an error */
598 }
599 else
600 {
Bram Moolenaar202795b2005-10-11 20:29:39 +0000601 filemess(curbuf, sfname, (char_u *)(
602# ifdef EFBIG
603 (errno == EFBIG) ? _("[File too big]") :
604# endif
605 _("[Permission Denied]")), 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606 curbuf->b_p_ro = TRUE; /* must use "w!" now */
607 }
608 }
609
610 return FAIL;
611 }
612
613 /*
614 * Only set the 'ro' flag for readonly files the first time they are
615 * loaded. Help files always get readonly mode
616 */
617 if ((check_readonly && file_readonly) || curbuf->b_help)
618 curbuf->b_p_ro = TRUE;
619
620 if (newfile)
621 {
622 curbuf->b_p_eol = TRUE;
623 curbuf->b_start_eol = TRUE;
624#ifdef FEAT_MBYTE
625 curbuf->b_p_bomb = FALSE;
626#endif
627 }
628
629 /* Create a swap file now, so that other Vims are warned that we are
630 * editing this file.
631 * Don't do this for a "nofile" or "nowrite" buffer type. */
632#ifdef FEAT_QUICKFIX
633 if (!bt_dontwrite(curbuf))
634#endif
635 {
636 check_need_swap(newfile);
637#ifdef UNIX
638 /* Set swap file protection bits after creating it. */
639 if (swap_mode > 0 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
640 (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
641#endif
642 }
643
Bram Moolenaarb815dac2005-12-07 20:59:24 +0000644#if defined(HAS_SWAP_EXISTS_ACTION)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000645 /* If "Quit" selected at ATTENTION dialog, don't load the file */
646 if (swap_exists_action == SEA_QUIT)
647 {
648 if (!read_buffer && !read_stdin)
649 close(fd);
650 return FAIL;
651 }
652#endif
653
654 ++no_wait_return; /* don't wait for return yet */
655
656 /*
657 * Set '[ mark to the line above where the lines go (line 1 if zero).
658 */
659 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
660 curbuf->b_op_start.col = 0;
661
662#ifdef FEAT_AUTOCMD
663 if (!read_buffer)
664 {
665 int m = msg_scroll;
666 int n = msg_scrolled;
667 buf_T *old_curbuf = curbuf;
668
669 /*
670 * The file must be closed again, the autocommands may want to change
671 * the file before reading it.
672 */
673 if (!read_stdin)
674 close(fd); /* ignore errors */
675
676 /*
677 * The output from the autocommands should not overwrite anything and
678 * should not be overwritten: Set msg_scroll, restore its value if no
679 * output was done.
680 */
681 msg_scroll = TRUE;
682 if (filtering)
683 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
684 FALSE, curbuf, eap);
685 else if (read_stdin)
686 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
687 FALSE, curbuf, eap);
688 else if (newfile)
689 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
690 FALSE, curbuf, eap);
691 else
692 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
693 FALSE, NULL, eap);
694 if (msg_scrolled == n)
695 msg_scroll = m;
696
697#ifdef FEAT_EVAL
698 if (aborting()) /* autocmds may abort script processing */
699 {
700 --no_wait_return;
701 msg_scroll = msg_save;
702 curbuf->b_p_ro = TRUE; /* must use "w!" now */
703 return FAIL;
704 }
705#endif
706 /*
707 * Don't allow the autocommands to change the current buffer.
708 * Try to re-open the file.
709 */
710 if (!read_stdin && (curbuf != old_curbuf
711 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
712 {
713 --no_wait_return;
714 msg_scroll = msg_save;
715 if (fd < 0)
716 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
717 else
718 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
719 curbuf->b_p_ro = TRUE; /* must use "w!" now */
720 return FAIL;
721 }
722 }
723#endif /* FEAT_AUTOCMD */
724
725 /* Autocommands may add lines to the file, need to check if it is empty */
726 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
727
728 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
729 {
730 /*
731 * Show the user that we are busy reading the input. Sometimes this
732 * may take a while. When reading from stdin another program may
733 * still be running, don't move the cursor to the last line, unless
734 * always using the GUI.
735 */
736 if (read_stdin)
737 {
738#ifndef ALWAYS_USE_GUI
739 mch_msg(_("Vim: Reading from stdin...\n"));
740#endif
741#ifdef FEAT_GUI
742 /* Also write a message in the GUI window, if there is one. */
743 if (gui.in_use && !gui.dying && !gui.starting)
744 {
745 p = (char_u *)_("Reading from stdin...");
746 gui_write(p, (int)STRLEN(p));
747 }
748#endif
749 }
750 else if (!read_buffer)
751 filemess(curbuf, sfname, (char_u *)"", 0);
752 }
753
754 msg_scroll = FALSE; /* overwrite the file message */
755
756 /*
757 * Set linecnt now, before the "retry" caused by a wrong guess for
758 * fileformat, and after the autocommands, which may change them.
759 */
760 linecnt = curbuf->b_ml.ml_line_count;
761
762#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000763 /* "++bad=" argument. */
764 if (eap != NULL && eap->bad_char != 0)
Bram Moolenaar195d6352005-12-19 22:08:24 +0000765 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000766 bad_char_behavior = eap->bad_char;
Bram Moolenaar195d6352005-12-19 22:08:24 +0000767 if (newfile)
768 curbuf->b_bad_char = eap->bad_char;
769 }
770 else
771 curbuf->b_bad_char = 0;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000772
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000774 * Decide which 'encoding' to use or use first.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775 */
776 if (eap != NULL && eap->force_enc != 0)
777 {
778 fenc = enc_canonize(eap->cmd + eap->force_enc);
779 fenc_alloced = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000780 keep_dest_enc = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781 }
782 else if (curbuf->b_p_bin)
783 {
784 fenc = (char_u *)""; /* binary: don't convert */
785 fenc_alloced = FALSE;
786 }
787 else if (curbuf->b_help)
788 {
789 char_u firstline[80];
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000790 int fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000791
792 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
793 * fails it must be latin1.
794 * Always do this when 'encoding' is "utf-8". Otherwise only do
795 * this when needed to avoid [converted] remarks all the time.
796 * It is needed when the first line contains non-ASCII characters.
797 * That is only in *.??x files. */
798 fenc = (char_u *)"latin1";
799 c = enc_utf8;
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000800 if (!c && !read_stdin)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000801 {
Bram Moolenaar75c50c42005-06-04 22:06:24 +0000802 fc = fname[STRLEN(fname) - 1];
803 if (TOLOWER_ASC(fc) == 'x')
804 {
805 /* Read the first line (and a bit more). Immediately rewind to
806 * the start of the file. If the read() fails "len" is -1. */
807 len = vim_read(fd, firstline, 80);
808 lseek(fd, (off_t)0L, SEEK_SET);
809 for (p = firstline; p < firstline + len; ++p)
810 if (*p >= 0x80)
811 {
812 c = TRUE;
813 break;
814 }
815 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 }
817
818 if (c)
819 {
820 fenc_next = fenc;
821 fenc = (char_u *)"utf-8";
822
823 /* When the file is utf-8 but a character doesn't fit in
824 * 'encoding' don't retry. In help text editing utf-8 bytes
825 * doesn't make sense. */
826 keep_dest_enc = TRUE;
827 }
828 fenc_alloced = FALSE;
829 }
830 else if (*p_fencs == NUL)
831 {
832 fenc = curbuf->b_p_fenc; /* use format from buffer */
833 fenc_alloced = FALSE;
834 }
835 else
836 {
837 fenc_next = p_fencs; /* try items in 'fileencodings' */
838 fenc = next_fenc(&fenc_next);
839 fenc_alloced = TRUE;
840 }
841#endif
842
843 /*
844 * Jump back here to retry reading the file in different ways.
845 * Reasons to retry:
846 * - encoding conversion failed: try another one from "fenc_next"
847 * - BOM detected and fenc was set, need to setup conversion
848 * - "fileformat" check failed: try another
849 *
850 * Variables set for special retry actions:
851 * "file_rewind" Rewind the file to start reading it again.
852 * "advance_fenc" Advance "fenc" using "fenc_next".
853 * "skip_read" Re-use already read bytes (BOM detected).
854 * "did_iconv" iconv() conversion failed, try 'charconvert'.
855 * "keep_fileformat" Don't reset "fileformat".
856 *
857 * Other status indicators:
858 * "tmpname" When != NULL did conversion with 'charconvert'.
859 * Output file has to be deleted afterwards.
860 * "iconv_fd" When != -1 did conversion with iconv().
861 */
862retry:
863
864 if (file_rewind)
865 {
866 if (read_buffer)
867 {
868 read_buf_lnum = 1;
869 read_buf_col = 0;
870 }
871 else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
872 {
873 /* Can't rewind the file, give up. */
874 error = TRUE;
875 goto failed;
876 }
877 /* Delete the previously read lines. */
878 while (lnum > from)
879 ml_delete(lnum--, FALSE);
880 file_rewind = FALSE;
881#ifdef FEAT_MBYTE
882 if (newfile)
883 curbuf->b_p_bomb = FALSE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000884 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885#endif
886 }
887
888 /*
889 * When retrying with another "fenc" and the first time "fileformat"
890 * will be reset.
891 */
892 if (keep_fileformat)
893 keep_fileformat = FALSE;
894 else
895 {
896 if (eap != NULL && eap->force_ff != 0)
897 fileformat = get_fileformat_force(curbuf, eap);
898 else if (curbuf->b_p_bin)
899 fileformat = EOL_UNIX; /* binary: use Unix format */
900 else if (*p_ffs == NUL)
901 fileformat = get_fileformat(curbuf);/* use format from buffer */
902 else
903 fileformat = EOL_UNKNOWN; /* detect from file */
904 }
905
906#ifdef FEAT_MBYTE
907# ifdef USE_ICONV
908 if (iconv_fd != (iconv_t)-1)
909 {
910 /* aborted conversion with iconv(), close the descriptor */
911 iconv_close(iconv_fd);
912 iconv_fd = (iconv_t)-1;
913 }
914# endif
915
916 if (advance_fenc)
917 {
918 /*
919 * Try the next entry in 'fileencodings'.
920 */
921 advance_fenc = FALSE;
922
923 if (eap != NULL && eap->force_enc != 0)
924 {
925 /* Conversion given with "++cc=" wasn't possible, read
926 * without conversion. */
927 notconverted = TRUE;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +0000928 conv_error = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 if (fenc_alloced)
930 vim_free(fenc);
931 fenc = (char_u *)"";
932 fenc_alloced = FALSE;
933 }
934 else
935 {
936 if (fenc_alloced)
937 vim_free(fenc);
938 if (fenc_next != NULL)
939 {
940 fenc = next_fenc(&fenc_next);
941 fenc_alloced = (fenc_next != NULL);
942 }
943 else
944 {
945 fenc = (char_u *)"";
946 fenc_alloced = FALSE;
947 }
948 }
949 if (tmpname != NULL)
950 {
951 mch_remove(tmpname); /* delete converted file */
952 vim_free(tmpname);
953 tmpname = NULL;
954 }
955 }
956
957 /*
958 * Conversion is required when the encoding of the file is different
959 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4 (requires
960 * conversion to UTF-8).
961 */
962 fio_flags = 0;
963 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
964 if (converted || enc_unicode != 0)
965 {
966
967 /* "ucs-bom" means we need to check the first bytes of the file
968 * for a BOM. */
969 if (STRCMP(fenc, ENC_UCSBOM) == 0)
970 fio_flags = FIO_UCSBOM;
971
972 /*
973 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
974 * done. This is handled below after read(). Prepare the
975 * fio_flags to avoid having to parse the string each time.
976 * Also check for Unicode to Latin1 conversion, because iconv()
977 * appears not to handle this correctly. This works just like
978 * conversion to UTF-8 except how the resulting character is put in
979 * the buffer.
980 */
981 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
982 fio_flags = get_fio_flags(fenc);
983
984# ifdef WIN3264
985 /*
986 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
987 * is handled with MultiByteToWideChar().
988 */
989 if (fio_flags == 0)
990 fio_flags = get_win_fio_flags(fenc);
991# endif
992
993# ifdef MACOS_X
994 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
995 if (fio_flags == 0)
996 fio_flags = get_mac_fio_flags(fenc);
997# endif
998
999# ifdef USE_ICONV
1000 /*
1001 * Try using iconv() if we can't convert internally.
1002 */
1003 if (fio_flags == 0
1004# ifdef FEAT_EVAL
1005 && !did_iconv
1006# endif
1007 )
1008 iconv_fd = (iconv_t)my_iconv_open(
1009 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
1010# endif
1011
1012# ifdef FEAT_EVAL
1013 /*
1014 * Use the 'charconvert' expression when conversion is required
1015 * and we can't do it internally or with iconv().
1016 */
1017 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1018# ifdef USE_ICONV
1019 && iconv_fd == (iconv_t)-1
1020# endif
1021 )
1022 {
1023# ifdef USE_ICONV
1024 did_iconv = FALSE;
1025# endif
1026 /* Skip conversion when it's already done (retry for wrong
1027 * "fileformat"). */
1028 if (tmpname == NULL)
1029 {
1030 tmpname = readfile_charconvert(fname, fenc, &fd);
1031 if (tmpname == NULL)
1032 {
1033 /* Conversion failed. Try another one. */
1034 advance_fenc = TRUE;
1035 if (fd < 0)
1036 {
1037 /* Re-opening the original file failed! */
1038 EMSG(_("E202: Conversion made file unreadable!"));
1039 error = TRUE;
1040 goto failed;
1041 }
1042 goto retry;
1043 }
1044 }
1045 }
1046 else
1047# endif
1048 {
1049 if (fio_flags == 0
1050# ifdef USE_ICONV
1051 && iconv_fd == (iconv_t)-1
1052# endif
1053 )
1054 {
1055 /* Conversion wanted but we can't.
1056 * Try the next conversion in 'fileencodings' */
1057 advance_fenc = TRUE;
1058 goto retry;
1059 }
1060 }
1061 }
1062
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001063 /* Set "can_retry" when it's possible to rewind the file and try with
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001065 * stdin or fixed at a specific encoding. */
1066 can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067#endif
1068
1069 if (!skip_read)
1070 {
1071 linerest = 0;
1072 filesize = 0;
1073 skip_count = lines_to_skip;
1074 read_count = lines_to_read;
1075#ifdef FEAT_MBYTE
1076 conv_restlen = 0;
1077#endif
1078 }
1079
1080 while (!error && !got_int)
1081 {
1082 /*
1083 * We allocate as much space for the file as we can get, plus
1084 * space for the old line plus room for one terminating NUL.
1085 * The amount is limited by the fact that read() only can read
1086 * upto max_unsigned characters (and other things).
1087 */
1088#if SIZEOF_INT <= 2
1089 if (linerest >= 0x7ff0)
1090 {
1091 ++split;
1092 *ptr = NL; /* split line by inserting a NL */
1093 size = 1;
1094 }
1095 else
1096#endif
1097 {
1098 if (!skip_read)
1099 {
1100#if SIZEOF_INT > 2
1101# ifdef __TANDEM
1102 size = SSIZE_MAX; /* use max I/O size, 52K */
1103# else
1104 size = 0x10000L; /* use buffer >= 64K */
1105# endif
1106#else
1107 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1108#endif
1109
1110 for ( ; size >= 10; size = (long_u)size >> 1)
1111 {
1112 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1113 FALSE)) != NULL)
1114 break;
1115 }
1116 if (new_buffer == NULL)
1117 {
1118 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1119 error = TRUE;
1120 break;
1121 }
1122 if (linerest) /* copy characters from the previous buffer */
1123 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1124 vim_free(buffer);
1125 buffer = new_buffer;
1126 ptr = buffer + linerest;
1127 line_start = buffer;
1128
1129#ifdef FEAT_MBYTE
1130 /* May need room to translate into.
1131 * For iconv() we don't really know the required space, use a
1132 * factor ICONV_MULT.
1133 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1134 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1135 * become up to 4 bytes, size must be multiple of 2
1136 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1137 * multiple of 2
1138 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1139 * multiple of 4 */
1140 real_size = size;
1141# ifdef USE_ICONV
1142 if (iconv_fd != (iconv_t)-1)
1143 size = size / ICONV_MULT;
1144 else
1145# endif
1146 if (fio_flags & FIO_LATIN1)
1147 size = size / 2;
1148 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1149 size = (size * 2 / 3) & ~1;
1150 else if (fio_flags & FIO_UCS4)
1151 size = (size * 2 / 3) & ~3;
1152 else if (fio_flags == FIO_UCSBOM)
1153 size = size / ICONV_MULT; /* worst case */
1154# ifdef WIN3264
1155 else if (fio_flags & FIO_CODEPAGE)
1156 size = size / ICONV_MULT; /* also worst case */
1157# endif
1158# ifdef MACOS_X
1159 else if (fio_flags & FIO_MACROMAN)
1160 size = size / ICONV_MULT; /* also worst case */
1161# endif
1162#endif
1163
1164#ifdef FEAT_MBYTE
1165 if (conv_restlen > 0)
1166 {
1167 /* Insert unconverted bytes from previous line. */
1168 mch_memmove(ptr, conv_rest, conv_restlen);
1169 ptr += conv_restlen;
1170 size -= conv_restlen;
1171 }
1172#endif
1173
1174 if (read_buffer)
1175 {
1176 /*
1177 * Read bytes from curbuf. Used for converting text read
1178 * from stdin.
1179 */
1180 if (read_buf_lnum > from)
1181 size = 0;
1182 else
1183 {
1184 int n, ni;
1185 long tlen;
1186
1187 tlen = 0;
1188 for (;;)
1189 {
1190 p = ml_get(read_buf_lnum) + read_buf_col;
1191 n = (int)STRLEN(p);
1192 if ((int)tlen + n + 1 > size)
1193 {
1194 /* Filled up to "size", append partial line.
1195 * Change NL to NUL to reverse the effect done
1196 * below. */
1197 n = size - tlen;
1198 for (ni = 0; ni < n; ++ni)
1199 {
1200 if (p[ni] == NL)
1201 ptr[tlen++] = NUL;
1202 else
1203 ptr[tlen++] = p[ni];
1204 }
1205 read_buf_col += n;
1206 break;
1207 }
1208 else
1209 {
1210 /* Append whole line and new-line. Change NL
1211 * to NUL to reverse the effect done below. */
1212 for (ni = 0; ni < n; ++ni)
1213 {
1214 if (p[ni] == NL)
1215 ptr[tlen++] = NUL;
1216 else
1217 ptr[tlen++] = p[ni];
1218 }
1219 ptr[tlen++] = NL;
1220 read_buf_col = 0;
1221 if (++read_buf_lnum > from)
1222 {
1223 /* When the last line didn't have an
1224 * end-of-line don't add it now either. */
1225 if (!curbuf->b_p_eol)
1226 --tlen;
1227 size = tlen;
1228 break;
1229 }
1230 }
1231 }
1232 }
1233 }
1234 else
1235 {
1236 /*
1237 * Read bytes from the file.
1238 */
1239 size = vim_read(fd, ptr, size);
1240 }
1241
1242 if (size <= 0)
1243 {
1244 if (size < 0) /* read error */
1245 error = TRUE;
1246#ifdef FEAT_MBYTE
1247 else if (conv_restlen > 0)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001248 {
1249 /* Reached end-of-file but some trailing bytes could
1250 * not be converted. Trucated file? */
1251 if (conv_error == 0)
1252 conv_error = linecnt;
1253 if (bad_char_behavior != BAD_DROP)
1254 {
1255 fio_flags = 0; /* don't convert this */
1256 if (bad_char_behavior == BAD_KEEP)
1257 {
1258 /* Keep the trailing bytes as-is. */
1259 size = conv_restlen;
1260 ptr -= conv_restlen;
1261 }
1262 else
1263 {
1264 /* Replace the trailing bytes with the
1265 * replacement character. */
1266 size = 1;
1267 *--ptr = bad_char_behavior;
1268 }
1269 conv_restlen = 0;
1270 }
1271 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272#endif
1273 }
1274
1275#ifdef FEAT_CRYPT
1276 /*
1277 * At start of file: Check for magic number of encryption.
1278 */
1279 if (filesize == 0)
1280 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
1281 &filesize, newfile);
1282 /*
1283 * Decrypt the read bytes.
1284 */
1285 if (cryptkey != NULL && size > 0)
1286 for (p = ptr; p < ptr + size; ++p)
1287 ZDECODE(*p);
1288#endif
1289 }
1290 skip_read = FALSE;
1291
1292#ifdef FEAT_MBYTE
1293 /*
1294 * At start of file (or after crypt magic number): Check for BOM.
1295 * Also check for a BOM for other Unicode encodings, but not after
1296 * converting with 'charconvert' or when a BOM has already been
1297 * found.
1298 */
1299 if ((filesize == 0
1300# ifdef FEAT_CRYPT
1301 || (filesize == CRYPT_MAGIC_LEN && cryptkey != NULL)
1302# endif
1303 )
1304 && (fio_flags == FIO_UCSBOM
1305 || (!curbuf->b_p_bomb
1306 && tmpname == NULL
1307 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1308 {
1309 char_u *ccname;
1310 int blen;
1311
1312 /* no BOM detection in a short file or in binary mode */
1313 if (size < 2 || curbuf->b_p_bin)
1314 ccname = NULL;
1315 else
1316 ccname = check_for_bom(ptr, size, &blen,
1317 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1318 if (ccname != NULL)
1319 {
1320 /* Remove BOM from the text */
1321 filesize += blen;
1322 size -= blen;
1323 mch_memmove(ptr, ptr + blen, (size_t)size);
1324 if (newfile)
1325 curbuf->b_p_bomb = TRUE;
1326 }
1327
1328 if (fio_flags == FIO_UCSBOM)
1329 {
1330 if (ccname == NULL)
1331 {
1332 /* No BOM detected: retry with next encoding. */
1333 advance_fenc = TRUE;
1334 }
1335 else
1336 {
1337 /* BOM detected: set "fenc" and jump back */
1338 if (fenc_alloced)
1339 vim_free(fenc);
1340 fenc = ccname;
1341 fenc_alloced = FALSE;
1342 }
1343 /* retry reading without getting new bytes or rewinding */
1344 skip_read = TRUE;
1345 goto retry;
1346 }
1347 }
1348#endif
1349 /*
1350 * Break here for a read error or end-of-file.
1351 */
1352 if (size <= 0)
1353 break;
1354
1355#ifdef FEAT_MBYTE
1356
1357 /* Include not converted bytes. */
1358 ptr -= conv_restlen;
1359 size += conv_restlen;
1360 conv_restlen = 0;
1361
1362# ifdef USE_ICONV
1363 if (iconv_fd != (iconv_t)-1)
1364 {
1365 /*
1366 * Attempt conversion of the read bytes to 'encoding' using
1367 * iconv().
1368 */
1369 const char *fromp;
1370 char *top;
1371 size_t from_size;
1372 size_t to_size;
1373
1374 fromp = (char *)ptr;
1375 from_size = size;
1376 ptr += size;
1377 top = (char *)ptr;
1378 to_size = real_size - size;
1379
1380 /*
1381 * If there is conversion error or not enough room try using
Bram Moolenaar19a09a12005-03-04 23:39:37 +00001382 * another conversion. Except for when there is no
1383 * alternative (help files).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001384 */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001385 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1386 &top, &to_size)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001387 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1388 || from_size > CONV_RESTLEN)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001389 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001390 if (can_retry)
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001391 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001392 if (conv_error == 0)
1393 conv_error = readfile_linenr(linecnt,
1394 ptr, (char_u *)top);
Bram Moolenaar42eeac32005-06-29 22:40:58 +00001395
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001396 /* Deal with a bad byte and continue with the next. */
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001397 ++fromp;
1398 --from_size;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001399 if (bad_char_behavior == BAD_KEEP)
1400 {
1401 *top++ = *(fromp - 1);
1402 --to_size;
1403 }
1404 else if (bad_char_behavior != BAD_DROP)
1405 {
1406 *top++ = bad_char_behavior;
1407 --to_size;
1408 }
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00001409 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001410
1411 if (from_size > 0)
1412 {
1413 /* Some remaining characters, keep them for the next
1414 * round. */
1415 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1416 conv_restlen = (int)from_size;
1417 }
1418
1419 /* move the linerest to before the converted characters */
1420 line_start = ptr - linerest;
1421 mch_memmove(line_start, buffer, (size_t)linerest);
1422 size = (long)((char_u *)top - ptr);
1423 }
1424# endif
1425
1426# ifdef WIN3264
1427 if (fio_flags & FIO_CODEPAGE)
1428 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001429 char_u *src, *dst;
1430 int u8c;
1431 WCHAR ucs2buf[3];
1432 int ucs2len;
1433 int codepage = FIO_GET_CP(fio_flags);
1434 int bytelen;
1435 int found_bad;
1436 char replstr[2];
1437
Bram Moolenaar071d4272004-06-13 20:20:40 +00001438 /*
1439 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001440 * a codepage, using standard MS-Windows functions. This
1441 * requires two steps:
1442 * 1. convert from 'fileencoding' to ucs-2
1443 * 2. convert from ucs-2 to 'encoding'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001444 *
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001445 * Because there may be illegal bytes AND an incomplete byte
1446 * sequence at the end, we may have to do the conversion one
1447 * character at a time to get it right.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001448 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001449
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001450 /* Replacement string for WideCharToMultiByte(). */
1451 if (bad_char_behavior > 0)
1452 replstr[0] = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001453 else
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001454 replstr[0] = '?';
1455 replstr[1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001456
1457 /*
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001458 * Move the bytes to the end of the buffer, so that we have
1459 * room to put the result at the start.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001460 */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001461 src = ptr + real_size - size;
1462 mch_memmove(src, ptr, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001463
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001464 /*
1465 * Do the conversion.
1466 */
1467 dst = ptr;
1468 size = size;
1469 while (size > 0)
1470 {
1471 found_bad = FALSE;
1472
1473# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1474 if (codepage == CP_UTF8)
1475 {
1476 /* Handle CP_UTF8 input ourselves to be able to handle
1477 * trailing bytes properly.
1478 * Get one UTF-8 character from src. */
1479 bytelen = utf_ptr2len_len(src, size);
1480 if (bytelen > size)
1481 {
1482 /* Only got some bytes of a character. Normally
1483 * it's put in "conv_rest", but if it's too long
1484 * deal with it as if they were illegal bytes. */
1485 if (bytelen <= CONV_RESTLEN)
1486 break;
1487
1488 /* weird overlong byte sequence */
1489 bytelen = size;
1490 found_bad = TRUE;
1491 }
1492 else
1493 {
1494 u8c = utf_ptr2char(src);
Bram Moolenaar86e01082005-12-29 22:45:34 +00001495 if (u8c > 0xffff || (*src >= 0x80 && bytelen == 1))
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001496 found_bad = TRUE;
1497 ucs2buf[0] = u8c;
1498 ucs2len = 1;
1499 }
1500 }
1501 else
1502# endif
1503 {
1504 /* We don't know how long the byte sequence is, try
1505 * from one to three bytes. */
1506 for (bytelen = 1; bytelen <= size && bytelen <= 3;
1507 ++bytelen)
1508 {
1509 ucs2len = MultiByteToWideChar(codepage,
1510 MB_ERR_INVALID_CHARS,
1511 (LPCSTR)src, bytelen,
1512 ucs2buf, 3);
1513 if (ucs2len > 0)
1514 break;
1515 }
1516 if (ucs2len == 0)
1517 {
1518 /* If we have only one byte then it's probably an
1519 * incomplete byte sequence. Otherwise discard
1520 * one byte as a bad character. */
1521 if (size == 1)
1522 break;
1523 found_bad = TRUE;
1524 bytelen = 1;
1525 }
1526 }
1527
1528 if (!found_bad)
1529 {
1530 int i;
1531
1532 /* Convert "ucs2buf[ucs2len]" to 'enc' in "dst". */
1533 if (enc_utf8)
1534 {
1535 /* From UCS-2 to UTF-8. Cannot fail. */
1536 for (i = 0; i < ucs2len; ++i)
1537 dst += utf_char2bytes(ucs2buf[i], dst);
1538 }
1539 else
1540 {
1541 BOOL bad = FALSE;
1542 int dstlen;
1543
1544 /* From UCS-2 to "enc_codepage". If the
1545 * conversion uses the default character "?",
1546 * the data doesn't fit in this encoding. */
1547 dstlen = WideCharToMultiByte(enc_codepage, 0,
1548 (LPCWSTR)ucs2buf, ucs2len,
1549 (LPSTR)dst, (src - dst),
1550 replstr, &bad);
1551 if (bad)
1552 found_bad = TRUE;
1553 else
1554 dst += dstlen;
1555 }
1556 }
1557
1558 if (found_bad)
1559 {
1560 /* Deal with bytes we can't convert. */
1561 if (can_retry)
1562 goto rewind_retry;
1563 if (conv_error == 0)
1564 conv_error = readfile_linenr(linecnt, ptr, dst);
1565 if (bad_char_behavior != BAD_DROP)
1566 {
1567 if (bad_char_behavior == BAD_KEEP)
1568 {
1569 mch_memmove(dst, src, bytelen);
1570 dst += bytelen;
1571 }
1572 else
1573 *dst++ = bad_char_behavior;
1574 }
1575 }
1576
1577 src += bytelen;
1578 size -= bytelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001579 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001580
1581 if (size > 0)
1582 {
1583 /* An incomplete byte sequence remaining. */
1584 mch_memmove(conv_rest, src, size);
1585 conv_restlen = size;
1586 }
1587
1588 /* The new size is equal to how much "dst" was advanced. */
1589 size = dst - ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001590 }
1591 else
1592# endif
1593# ifdef MACOS_X
1594 if (fio_flags & FIO_MACROMAN)
1595 {
1596 /*
1597 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001598 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001599 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001600 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001601 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001602 }
1603 else
1604# endif
1605 if (fio_flags != 0)
1606 {
1607 int u8c;
1608 char_u *dest;
1609 char_u *tail = NULL;
1610
1611 /*
1612 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1613 * "enc_utf8" not set: Convert Unicode to Latin1.
1614 * Go from end to start through the buffer, because the number
1615 * of bytes may increase.
1616 * "dest" points to after where the UTF-8 bytes go, "p" points
1617 * to after the next character to convert.
1618 */
1619 dest = ptr + real_size;
1620 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1621 {
1622 p = ptr + size;
1623 if (fio_flags == FIO_UTF8)
1624 {
1625 /* Check for a trailing incomplete UTF-8 sequence */
1626 tail = ptr + size - 1;
1627 while (tail > ptr && (*tail & 0xc0) == 0x80)
1628 --tail;
1629 if (tail + utf_byte2len(*tail) <= ptr + size)
1630 tail = NULL;
1631 else
1632 p = tail;
1633 }
1634 }
1635 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1636 {
1637 /* Check for a trailing byte */
1638 p = ptr + (size & ~1);
1639 if (size & 1)
1640 tail = p;
1641 if ((fio_flags & FIO_UTF16) && p > ptr)
1642 {
1643 /* Check for a trailing leading word */
1644 if (fio_flags & FIO_ENDIAN_L)
1645 {
1646 u8c = (*--p << 8);
1647 u8c += *--p;
1648 }
1649 else
1650 {
1651 u8c = *--p;
1652 u8c += (*--p << 8);
1653 }
1654 if (u8c >= 0xd800 && u8c <= 0xdbff)
1655 tail = p;
1656 else
1657 p += 2;
1658 }
1659 }
1660 else /* FIO_UCS4 */
1661 {
1662 /* Check for trailing 1, 2 or 3 bytes */
1663 p = ptr + (size & ~3);
1664 if (size & 3)
1665 tail = p;
1666 }
1667
1668 /* If there is a trailing incomplete sequence move it to
1669 * conv_rest[]. */
1670 if (tail != NULL)
1671 {
1672 conv_restlen = (int)((ptr + size) - tail);
1673 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1674 size -= conv_restlen;
1675 }
1676
1677
1678 while (p > ptr)
1679 {
1680 if (fio_flags & FIO_LATIN1)
1681 u8c = *--p;
1682 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1683 {
1684 if (fio_flags & FIO_ENDIAN_L)
1685 {
1686 u8c = (*--p << 8);
1687 u8c += *--p;
1688 }
1689 else
1690 {
1691 u8c = *--p;
1692 u8c += (*--p << 8);
1693 }
1694 if ((fio_flags & FIO_UTF16)
1695 && u8c >= 0xdc00 && u8c <= 0xdfff)
1696 {
1697 int u16c;
1698
1699 if (p == ptr)
1700 {
1701 /* Missing leading word. */
1702 if (can_retry)
1703 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001704 if (conv_error == 0)
1705 conv_error = readfile_linenr(linecnt,
1706 ptr, p);
1707 if (bad_char_behavior == BAD_DROP)
1708 continue;
1709 if (bad_char_behavior != BAD_KEEP)
1710 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711 }
1712
1713 /* found second word of double-word, get the first
1714 * word and compute the resulting character */
1715 if (fio_flags & FIO_ENDIAN_L)
1716 {
1717 u16c = (*--p << 8);
1718 u16c += *--p;
1719 }
1720 else
1721 {
1722 u16c = *--p;
1723 u16c += (*--p << 8);
1724 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001725 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1726 + (u8c & 0x3ff);
1727
Bram Moolenaar071d4272004-06-13 20:20:40 +00001728 /* Check if the word is indeed a leading word. */
1729 if (u16c < 0xd800 || u16c > 0xdbff)
1730 {
1731 if (can_retry)
1732 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001733 if (conv_error == 0)
1734 conv_error = readfile_linenr(linecnt,
1735 ptr, p);
1736 if (bad_char_behavior == BAD_DROP)
1737 continue;
1738 if (bad_char_behavior != BAD_KEEP)
1739 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001740 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001741 }
1742 }
1743 else if (fio_flags & FIO_UCS4)
1744 {
1745 if (fio_flags & FIO_ENDIAN_L)
1746 {
1747 u8c = (*--p << 24);
1748 u8c += (*--p << 16);
1749 u8c += (*--p << 8);
1750 u8c += *--p;
1751 }
1752 else /* big endian */
1753 {
1754 u8c = *--p;
1755 u8c += (*--p << 8);
1756 u8c += (*--p << 16);
1757 u8c += (*--p << 24);
1758 }
1759 }
1760 else /* UTF-8 */
1761 {
1762 if (*--p < 0x80)
1763 u8c = *p;
1764 else
1765 {
1766 len = utf_head_off(ptr, p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001767 p -= len;
1768 u8c = utf_ptr2char(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001769 if (len == 0)
1770 {
1771 /* Not a valid UTF-8 character, retry with
1772 * another fenc when possible, otherwise just
1773 * report the error. */
1774 if (can_retry)
1775 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001776 if (conv_error == 0)
1777 conv_error = readfile_linenr(linecnt,
1778 ptr, p);
1779 if (bad_char_behavior == BAD_DROP)
1780 continue;
1781 if (bad_char_behavior != BAD_KEEP)
1782 u8c = bad_char_behavior;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001784 }
1785 }
1786 if (enc_utf8) /* produce UTF-8 */
1787 {
1788 dest -= utf_char2len(u8c);
1789 (void)utf_char2bytes(u8c, dest);
1790 }
1791 else /* produce Latin1 */
1792 {
1793 --dest;
1794 if (u8c >= 0x100)
1795 {
1796 /* character doesn't fit in latin1, retry with
1797 * another fenc when possible, otherwise just
1798 * report the error. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001799 if (can_retry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001800 goto rewind_retry;
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001801 if (conv_error == 0)
1802 conv_error = readfile_linenr(linecnt, ptr, p);
1803 if (bad_char_behavior == BAD_DROP)
1804 ++dest;
1805 else if (bad_char_behavior == BAD_KEEP)
1806 *dest = u8c;
1807 else if (eap != NULL && eap->bad_char != 0)
1808 *dest = bad_char_behavior;
1809 else
1810 *dest = 0xBF;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001811 }
1812 else
1813 *dest = u8c;
1814 }
1815 }
1816
1817 /* move the linerest to before the converted characters */
1818 line_start = dest - linerest;
1819 mch_memmove(line_start, buffer, (size_t)linerest);
1820 size = (long)((ptr + real_size) - dest);
1821 ptr = dest;
1822 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001823 else if (enc_utf8 && conv_error == 0 && !curbuf->b_p_bin)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001824 {
1825 /* Reading UTF-8: Check if the bytes are valid UTF-8.
1826 * Need to start before "ptr" when part of the character was
1827 * read in the previous read() call. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001828 for (p = ptr - utf_head_off(buffer, ptr); ; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001829 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001830 int todo = (ptr + size) - p;
1831 int l;
1832
1833 if (todo <= 0)
1834 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835 if (*p >= 0x80)
1836 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001837 /* A length of 1 means it's an illegal byte. Accept
1838 * an incomplete character at the end though, the next
1839 * read() will get the next bytes, we'll check it
1840 * then. */
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001841 l = utf_ptr2len_len(p, todo);
1842 if (l > todo)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001843 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001844 /* Incomplete byte sequence, the next read()
1845 * should get them and check the bytes. */
1846 p += todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847 break;
1848 }
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001849 if (l == 1)
1850 {
1851 /* Illegal byte. If we can try another encoding
1852 * do that. */
1853 if (can_retry)
1854 break;
1855
1856 /* Remember the first linenr with an illegal byte */
1857 if (illegal_byte == 0)
1858 illegal_byte = readfile_linenr(linecnt, ptr, p);
1859# ifdef USE_ICONV
1860 /* When we did a conversion report an error. */
1861 if (iconv_fd != (iconv_t)-1 && conv_error == 0)
1862 conv_error = readfile_linenr(linecnt, ptr, p);
1863# endif
1864
1865 /* Drop, keep or replace the bad byte. */
1866 if (bad_char_behavior == BAD_DROP)
1867 {
1868 mch_memmove(p, p+1, todo - 1);
1869 --p;
1870 --size;
1871 }
1872 else if (bad_char_behavior != BAD_KEEP)
1873 *p = bad_char_behavior;
1874 }
1875 p += l - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 }
1877 }
1878 if (p < ptr + size)
1879 {
1880 /* Detected a UTF-8 error. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881rewind_retry:
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001882 /* Retry reading with another conversion. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001883# if defined(FEAT_EVAL) && defined(USE_ICONV)
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001884 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
1885 /* iconv() failed, try 'charconvert' */
1886 did_iconv = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001887 else
1888# endif
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001889 /* use next item from 'fileencodings' */
1890 advance_fenc = TRUE;
1891 file_rewind = TRUE;
1892 goto retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001893 }
1894 }
1895#endif
1896
1897 /* count the number of characters (after conversion!) */
1898 filesize += size;
1899
1900 /*
1901 * when reading the first part of a file: guess EOL type
1902 */
1903 if (fileformat == EOL_UNKNOWN)
1904 {
1905 /* First try finding a NL, for Dos and Unix */
1906 if (try_dos || try_unix)
1907 {
1908 for (p = ptr; p < ptr + size; ++p)
1909 {
1910 if (*p == NL)
1911 {
1912 if (!try_unix
1913 || (try_dos && p > ptr && p[-1] == CAR))
1914 fileformat = EOL_DOS;
1915 else
1916 fileformat = EOL_UNIX;
1917 break;
1918 }
1919 }
1920
1921 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
1922 if (fileformat == EOL_UNIX && try_mac)
1923 {
1924 /* Need to reset the counters when retrying fenc. */
1925 try_mac = 1;
1926 try_unix = 1;
1927 for (; p >= ptr && *p != CAR; p--)
1928 ;
1929 if (p >= ptr)
1930 {
1931 for (p = ptr; p < ptr + size; ++p)
1932 {
1933 if (*p == NL)
1934 try_unix++;
1935 else if (*p == CAR)
1936 try_mac++;
1937 }
1938 if (try_mac > try_unix)
1939 fileformat = EOL_MAC;
1940 }
1941 }
1942 }
1943
1944 /* No NL found: may use Mac format */
1945 if (fileformat == EOL_UNKNOWN && try_mac)
1946 fileformat = EOL_MAC;
1947
1948 /* Still nothing found? Use first format in 'ffs' */
1949 if (fileformat == EOL_UNKNOWN)
1950 fileformat = default_fileformat();
1951
1952 /* if editing a new file: may set p_tx and p_ff */
1953 if (newfile)
1954 set_fileformat(fileformat, OPT_LOCAL);
1955 }
1956 }
1957
1958 /*
1959 * This loop is executed once for every character read.
1960 * Keep it fast!
1961 */
1962 if (fileformat == EOL_MAC)
1963 {
1964 --ptr;
1965 while (++ptr, --size >= 0)
1966 {
1967 /* catch most common case first */
1968 if ((c = *ptr) != NUL && c != CAR && c != NL)
1969 continue;
1970 if (c == NUL)
1971 *ptr = NL; /* NULs are replaced by newlines! */
1972 else if (c == NL)
1973 *ptr = CAR; /* NLs are replaced by CRs! */
1974 else
1975 {
1976 if (skip_count == 0)
1977 {
1978 *ptr = NUL; /* end of line */
1979 len = (colnr_T) (ptr - line_start + 1);
1980 if (ml_append(lnum, line_start, len, newfile) == FAIL)
1981 {
1982 error = TRUE;
1983 break;
1984 }
1985 ++lnum;
1986 if (--read_count == 0)
1987 {
1988 error = TRUE; /* break loop */
1989 line_start = ptr; /* nothing left to write */
1990 break;
1991 }
1992 }
1993 else
1994 --skip_count;
1995 line_start = ptr + 1;
1996 }
1997 }
1998 }
1999 else
2000 {
2001 --ptr;
2002 while (++ptr, --size >= 0)
2003 {
2004 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
2005 continue;
2006 if (c == NUL)
2007 *ptr = NL; /* NULs are replaced by newlines! */
2008 else
2009 {
2010 if (skip_count == 0)
2011 {
2012 *ptr = NUL; /* end of line */
2013 len = (colnr_T)(ptr - line_start + 1);
2014 if (fileformat == EOL_DOS)
2015 {
2016 if (ptr[-1] == CAR) /* remove CR */
2017 {
2018 ptr[-1] = NUL;
2019 --len;
2020 }
2021 /*
2022 * Reading in Dos format, but no CR-LF found!
2023 * When 'fileformats' includes "unix", delete all
2024 * the lines read so far and start all over again.
2025 * Otherwise give an error message later.
2026 */
2027 else if (ff_error != EOL_DOS)
2028 {
2029 if ( try_unix
2030 && !read_stdin
2031 && (read_buffer
2032 || lseek(fd, (off_t)0L, SEEK_SET) == 0))
2033 {
2034 fileformat = EOL_UNIX;
2035 if (newfile)
2036 set_fileformat(EOL_UNIX, OPT_LOCAL);
2037 file_rewind = TRUE;
2038 keep_fileformat = TRUE;
2039 goto retry;
2040 }
2041 ff_error = EOL_DOS;
2042 }
2043 }
2044 if (ml_append(lnum, line_start, len, newfile) == FAIL)
2045 {
2046 error = TRUE;
2047 break;
2048 }
2049 ++lnum;
2050 if (--read_count == 0)
2051 {
2052 error = TRUE; /* break loop */
2053 line_start = ptr; /* nothing left to write */
2054 break;
2055 }
2056 }
2057 else
2058 --skip_count;
2059 line_start = ptr + 1;
2060 }
2061 }
2062 }
2063 linerest = (long)(ptr - line_start);
2064 ui_breakcheck();
2065 }
2066
2067failed:
2068 /* not an error, max. number of lines reached */
2069 if (error && read_count == 0)
2070 error = FALSE;
2071
2072 /*
2073 * If we get EOF in the middle of a line, note the fact and
2074 * complete the line ourselves.
2075 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
2076 */
2077 if (!error
2078 && !got_int
2079 && linerest != 0
2080 && !(!curbuf->b_p_bin
2081 && fileformat == EOL_DOS
2082 && *line_start == Ctrl_Z
2083 && ptr == line_start + 1))
2084 {
2085 if (newfile) /* remember for when writing */
2086 curbuf->b_p_eol = FALSE;
2087 *ptr = NUL;
2088 if (ml_append(lnum, line_start,
2089 (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
2090 error = TRUE;
2091 else
2092 read_no_eol_lnum = ++lnum;
2093 }
2094
2095 if (newfile)
2096 save_file_ff(curbuf); /* remember the current file format */
2097
2098#ifdef FEAT_CRYPT
2099 if (cryptkey != curbuf->b_p_key)
2100 vim_free(cryptkey);
2101#endif
2102
2103#ifdef FEAT_MBYTE
2104 /* If editing a new file: set 'fenc' for the current buffer. */
2105 if (newfile)
2106 set_string_option_direct((char_u *)"fenc", -1, fenc,
2107 OPT_FREE|OPT_LOCAL);
2108 if (fenc_alloced)
2109 vim_free(fenc);
2110# ifdef USE_ICONV
2111 if (iconv_fd != (iconv_t)-1)
2112 {
2113 iconv_close(iconv_fd);
2114 iconv_fd = (iconv_t)-1;
2115 }
2116# endif
2117#endif
2118
2119 if (!read_buffer && !read_stdin)
2120 close(fd); /* errors are ignored */
2121 vim_free(buffer);
2122
2123#ifdef HAVE_DUP
2124 if (read_stdin)
2125 {
2126 /* Use stderr for stdin, makes shell commands work. */
2127 close(0);
2128 dup(2);
2129 }
2130#endif
2131
2132#ifdef FEAT_MBYTE
2133 if (tmpname != NULL)
2134 {
2135 mch_remove(tmpname); /* delete converted file */
2136 vim_free(tmpname);
2137 }
2138#endif
2139 --no_wait_return; /* may wait for return now */
2140
2141 /*
2142 * In recovery mode everything but autocommands is skipped.
2143 */
2144 if (!recoverymode)
2145 {
2146 /* need to delete the last line, which comes from the empty buffer */
2147 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2148 {
2149#ifdef FEAT_NETBEANS_INTG
2150 netbeansFireChanges = 0;
2151#endif
2152 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2153#ifdef FEAT_NETBEANS_INTG
2154 netbeansFireChanges = 1;
2155#endif
2156 --linecnt;
2157 }
2158 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2159 if (filesize == 0)
2160 linecnt = 0;
2161 if (newfile || read_buffer)
2162 redraw_curbuf_later(NOT_VALID);
2163 else if (linecnt) /* appended at least one line */
2164 appended_lines_mark(from, linecnt);
2165
2166#ifdef FEAT_DIFF
2167 /* After reading the text into the buffer the diff info needs to be
2168 * updated. */
2169 if ((newfile || read_buffer))
2170 diff_invalidate();
2171#endif
2172#ifndef ALWAYS_USE_GUI
2173 /*
2174 * If we were reading from the same terminal as where messages go,
2175 * the screen will have been messed up.
2176 * Switch on raw mode now and clear the screen.
2177 */
2178 if (read_stdin)
2179 {
2180 settmode(TMODE_RAW); /* set to raw mode */
2181 starttermcap();
2182 screenclear();
2183 }
2184#endif
2185
2186 if (got_int)
2187 {
2188 if (!(flags & READ_DUMMY))
2189 {
2190 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2191 if (newfile)
2192 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2193 }
2194 msg_scroll = msg_save;
2195#ifdef FEAT_VIMINFO
2196 check_marks_read();
2197#endif
2198 return OK; /* an interrupt isn't really an error */
2199 }
2200
2201 if (!filtering && !(flags & READ_DUMMY))
2202 {
2203 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2204 c = FALSE;
2205
2206#ifdef UNIX
2207# ifdef S_ISFIFO
2208 if (S_ISFIFO(perm)) /* fifo or socket */
2209 {
2210 STRCAT(IObuff, _("[fifo/socket]"));
2211 c = TRUE;
2212 }
2213# else
2214# ifdef S_IFIFO
2215 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2216 {
2217 STRCAT(IObuff, _("[fifo]"));
2218 c = TRUE;
2219 }
2220# endif
2221# ifdef S_IFSOCK
2222 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2223 {
2224 STRCAT(IObuff, _("[socket]"));
2225 c = TRUE;
2226 }
2227# endif
2228# endif
2229#endif
2230 if (curbuf->b_p_ro)
2231 {
2232 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2233 c = TRUE;
2234 }
2235 if (read_no_eol_lnum)
2236 {
2237 msg_add_eol();
2238 c = TRUE;
2239 }
2240 if (ff_error == EOL_DOS)
2241 {
2242 STRCAT(IObuff, _("[CR missing]"));
2243 c = TRUE;
2244 }
2245 if (ff_error == EOL_MAC)
2246 {
2247 STRCAT(IObuff, _("[NL found]"));
2248 c = TRUE;
2249 }
2250 if (split)
2251 {
2252 STRCAT(IObuff, _("[long lines split]"));
2253 c = TRUE;
2254 }
2255#ifdef FEAT_MBYTE
2256 if (notconverted)
2257 {
2258 STRCAT(IObuff, _("[NOT converted]"));
2259 c = TRUE;
2260 }
2261 else if (converted)
2262 {
2263 STRCAT(IObuff, _("[converted]"));
2264 c = TRUE;
2265 }
2266#endif
2267#ifdef FEAT_CRYPT
2268 if (cryptkey != NULL)
2269 {
2270 STRCAT(IObuff, _("[crypted]"));
2271 c = TRUE;
2272 }
2273#endif
2274#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002275 if (conv_error != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002276 {
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002277 sprintf((char *)IObuff + STRLEN(IObuff),
2278 _("[CONVERSION ERROR in line %ld]"), (long)conv_error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002279 c = TRUE;
2280 }
2281 else if (illegal_byte > 0)
2282 {
2283 sprintf((char *)IObuff + STRLEN(IObuff),
2284 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2285 c = TRUE;
2286 }
2287 else
2288#endif
2289 if (error)
2290 {
2291 STRCAT(IObuff, _("[READ ERRORS]"));
2292 c = TRUE;
2293 }
2294 if (msg_add_fileformat(fileformat))
2295 c = TRUE;
2296#ifdef FEAT_CRYPT
2297 if (cryptkey != NULL)
2298 msg_add_lines(c, (long)linecnt, filesize - CRYPT_MAGIC_LEN);
2299 else
2300#endif
2301 msg_add_lines(c, (long)linecnt, filesize);
2302
2303 vim_free(keep_msg);
2304 keep_msg = NULL;
2305 msg_scrolled_ign = TRUE;
2306#ifdef ALWAYS_USE_GUI
2307 /* Don't show the message when reading stdin, it would end up in a
2308 * message box (which might be shown when exiting!) */
2309 if (read_stdin || read_buffer)
2310 p = msg_may_trunc(FALSE, IObuff);
2311 else
2312#endif
2313 p = msg_trunc_attr(IObuff, FALSE, 0);
2314 if (read_stdin || read_buffer || restart_edit != 0
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00002315 || (msg_scrolled != 0 && !need_wait_return))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002316 {
2317 /* Need to repeat the message after redrawing when:
2318 * - When reading from stdin (the screen will be cleared next).
2319 * - When restart_edit is set (otherwise there will be a delay
2320 * before redrawing).
2321 * - When the screen was scrolled but there is no wait-return
2322 * prompt. */
2323 set_keep_msg(p);
2324 keep_msg_attr = 0;
2325 }
2326 msg_scrolled_ign = FALSE;
2327 }
2328
2329 /* with errors writing the file requires ":w!" */
2330 if (newfile && (error
2331#ifdef FEAT_MBYTE
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002332 || conv_error != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00002333#endif
2334 ))
2335 curbuf->b_p_ro = TRUE;
2336
2337 u_clearline(); /* cannot use "U" command after adding lines */
2338
2339 /*
2340 * In Ex mode: cursor at last new line.
2341 * Otherwise: cursor at first new line.
2342 */
2343 if (exmode_active)
2344 curwin->w_cursor.lnum = from + linecnt;
2345 else
2346 curwin->w_cursor.lnum = from + 1;
2347 check_cursor_lnum();
2348 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2349
2350 /*
2351 * Set '[ and '] marks to the newly read lines.
2352 */
2353 curbuf->b_op_start.lnum = from + 1;
2354 curbuf->b_op_start.col = 0;
2355 curbuf->b_op_end.lnum = from + linecnt;
2356 curbuf->b_op_end.col = 0;
2357 }
2358 msg_scroll = msg_save;
2359
2360#ifdef FEAT_VIMINFO
2361 /*
2362 * Get the marks before executing autocommands, so they can be used there.
2363 */
2364 check_marks_read();
2365#endif
2366
Bram Moolenaar071d4272004-06-13 20:20:40 +00002367 /*
2368 * Trick: We remember if the last line of the read didn't have
2369 * an eol for when writing it again. This is required for
2370 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
2371 */
2372 write_no_eol_lnum = read_no_eol_lnum;
2373
Bram Moolenaardf177f62005-02-22 08:39:57 +00002374#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00002375 if (!read_stdin && !read_buffer)
2376 {
2377 int m = msg_scroll;
2378 int n = msg_scrolled;
2379
2380 /* Save the fileformat now, otherwise the buffer will be considered
2381 * modified if the format/encoding was automatically detected. */
2382 if (newfile)
2383 save_file_ff(curbuf);
2384
2385 /*
2386 * The output from the autocommands should not overwrite anything and
2387 * should not be overwritten: Set msg_scroll, restore its value if no
2388 * output was done.
2389 */
2390 msg_scroll = TRUE;
2391 if (filtering)
2392 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2393 FALSE, curbuf, eap);
2394 else if (newfile)
2395 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2396 FALSE, curbuf, eap);
2397 else
2398 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2399 FALSE, NULL, eap);
2400 if (msg_scrolled == n)
2401 msg_scroll = m;
2402#ifdef FEAT_EVAL
2403 if (aborting()) /* autocmds may abort script processing */
2404 return FAIL;
2405#endif
2406 }
2407#endif
2408
2409 if (recoverymode && error)
2410 return FAIL;
2411 return OK;
2412}
2413
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00002414#ifdef FEAT_MBYTE
2415
2416/*
2417 * From the current line count and characters read after that, estimate the
2418 * line number where we are now.
2419 * Used for error messages that include a line number.
2420 */
2421 static linenr_T
2422readfile_linenr(linecnt, p, endp)
2423 linenr_T linecnt; /* line count before reading more bytes */
2424 char_u *p; /* start of more bytes read */
2425 char_u *endp; /* end of more bytes read */
2426{
2427 char_u *s;
2428 linenr_T lnum;
2429
2430 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2431 for (s = p; s < endp; ++s)
2432 if (*s == '\n')
2433 ++lnum;
2434 return lnum;
2435}
2436#endif
2437
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00002439 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2440 * equal to the buffer "buf". Used for calling readfile().
Bram Moolenaar071d4272004-06-13 20:20:40 +00002441 * Returns OK or FAIL.
2442 */
2443 int
2444prep_exarg(eap, buf)
2445 exarg_T *eap;
2446 buf_T *buf;
2447{
2448 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2449#ifdef FEAT_MBYTE
2450 + STRLEN(buf->b_p_fenc)
2451#endif
2452 + 15));
2453 if (eap->cmd == NULL)
2454 return FAIL;
2455
2456#ifdef FEAT_MBYTE
2457 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2458 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
Bram Moolenaar195d6352005-12-19 22:08:24 +00002459 eap->bad_char = buf->b_bad_char;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002460#else
2461 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2462#endif
2463 eap->force_ff = 7;
Bram Moolenaar195d6352005-12-19 22:08:24 +00002464
2465 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
2466 eap->forceit = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002467 return OK;
2468}
2469
2470#ifdef FEAT_MBYTE
2471/*
2472 * Find next fileencoding to use from 'fileencodings'.
2473 * "pp" points to fenc_next. It's advanced to the next item.
2474 * When there are no more items, an empty string is returned and *pp is set to
2475 * NULL.
2476 * When *pp is not set to NULL, the result is in allocated memory.
2477 */
2478 static char_u *
2479next_fenc(pp)
2480 char_u **pp;
2481{
2482 char_u *p;
2483 char_u *r;
2484
2485 if (**pp == NUL)
2486 {
2487 *pp = NULL;
2488 return (char_u *)"";
2489 }
2490 p = vim_strchr(*pp, ',');
2491 if (p == NULL)
2492 {
2493 r = enc_canonize(*pp);
2494 *pp += STRLEN(*pp);
2495 }
2496 else
2497 {
2498 r = vim_strnsave(*pp, (int)(p - *pp));
2499 *pp = p + 1;
2500 if (r != NULL)
2501 {
2502 p = enc_canonize(r);
2503 vim_free(r);
2504 r = p;
2505 }
2506 }
2507 if (r == NULL) /* out of memory */
2508 {
2509 r = (char_u *)"";
2510 *pp = NULL;
2511 }
2512 return r;
2513}
2514
2515# ifdef FEAT_EVAL
2516/*
2517 * Convert a file with the 'charconvert' expression.
2518 * This closes the file which is to be read, converts it and opens the
2519 * resulting file for reading.
2520 * Returns name of the resulting converted file (the caller should delete it
2521 * after reading it).
2522 * Returns NULL if the conversion failed ("*fdp" is not set) .
2523 */
2524 static char_u *
2525readfile_charconvert(fname, fenc, fdp)
2526 char_u *fname; /* name of input file */
2527 char_u *fenc; /* converted from */
2528 int *fdp; /* in/out: file descriptor of file */
2529{
2530 char_u *tmpname;
2531 char_u *errmsg = NULL;
2532
2533 tmpname = vim_tempname('r');
2534 if (tmpname == NULL)
2535 errmsg = (char_u *)_("Can't find temp file for conversion");
2536 else
2537 {
2538 close(*fdp); /* close the input file, ignore errors */
2539 *fdp = -1;
2540 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2541 fname, tmpname) == FAIL)
2542 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2543 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2544 O_RDONLY | O_EXTRA, 0)) < 0)
2545 errmsg = (char_u *)_("can't read output of 'charconvert'");
2546 }
2547
2548 if (errmsg != NULL)
2549 {
2550 /* Don't use emsg(), it breaks mappings, the retry with
2551 * another type of conversion might still work. */
2552 MSG(errmsg);
2553 if (tmpname != NULL)
2554 {
2555 mch_remove(tmpname); /* delete converted file */
2556 vim_free(tmpname);
2557 tmpname = NULL;
2558 }
2559 }
2560
2561 /* If the input file is closed, open it (caller should check for error). */
2562 if (*fdp < 0)
2563 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2564
2565 return tmpname;
2566}
2567# endif
2568
2569#endif
2570
2571#ifdef FEAT_VIMINFO
2572/*
2573 * Read marks for the current buffer from the viminfo file, when we support
2574 * buffer marks and the buffer has a name.
2575 */
2576 static void
2577check_marks_read()
2578{
2579 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2580 && curbuf->b_ffname != NULL)
2581 read_viminfo(NULL, FALSE, TRUE, FALSE);
2582
2583 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2584 * the ' parameter after opening a buffer. */
2585 curbuf->b_marks_read = TRUE;
2586}
2587#endif
2588
2589#ifdef FEAT_CRYPT
2590/*
2591 * Check for magic number used for encryption.
2592 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2593 * *filesizep are updated.
2594 * Return the (new) encryption key, NULL for no encryption.
2595 */
2596 static char_u *
2597check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
2598 char_u *cryptkey; /* previous encryption key or NULL */
2599 char_u *ptr; /* pointer to read bytes */
2600 long *sizep; /* length of read bytes */
2601 long *filesizep; /* nr of bytes used from file */
2602 int newfile; /* editing a new buffer */
2603{
2604 if (*sizep >= CRYPT_MAGIC_LEN
2605 && STRNCMP(ptr, CRYPT_MAGIC, CRYPT_MAGIC_LEN) == 0)
2606 {
2607 if (cryptkey == NULL)
2608 {
2609 if (*curbuf->b_p_key)
2610 cryptkey = curbuf->b_p_key;
2611 else
2612 {
2613 /* When newfile is TRUE, store the typed key
2614 * in the 'key' option and don't free it. */
2615 cryptkey = get_crypt_key(newfile, FALSE);
2616 /* check if empty key entered */
2617 if (cryptkey != NULL && *cryptkey == NUL)
2618 {
2619 if (cryptkey != curbuf->b_p_key)
2620 vim_free(cryptkey);
2621 cryptkey = NULL;
2622 }
2623 }
2624 }
2625
2626 if (cryptkey != NULL)
2627 {
2628 crypt_init_keys(cryptkey);
2629
2630 /* Remove magic number from the text */
2631 *filesizep += CRYPT_MAGIC_LEN;
2632 *sizep -= CRYPT_MAGIC_LEN;
2633 mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN, (size_t)*sizep);
2634 }
2635 }
2636 /* When starting to edit a new file which does not have
2637 * encryption, clear the 'key' option, except when
2638 * starting up (called with -x argument) */
2639 else if (newfile && *curbuf->b_p_key && !starting)
2640 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2641
2642 return cryptkey;
2643}
2644#endif
2645
2646#ifdef UNIX
2647 static void
2648set_file_time(fname, atime, mtime)
2649 char_u *fname;
2650 time_t atime; /* access time */
2651 time_t mtime; /* modification time */
2652{
2653# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
2654 struct utimbuf buf;
2655
2656 buf.actime = atime;
2657 buf.modtime = mtime;
2658 (void)utime((char *)fname, &buf);
2659# else
2660# if defined(HAVE_UTIMES)
2661 struct timeval tvp[2];
2662
2663 tvp[0].tv_sec = atime;
2664 tvp[0].tv_usec = 0;
2665 tvp[1].tv_sec = mtime;
2666 tvp[1].tv_usec = 0;
2667# ifdef NeXT
2668 (void)utimes((char *)fname, tvp);
2669# else
2670 (void)utimes((char *)fname, (const struct timeval *)&tvp);
2671# endif
2672# endif
2673# endif
2674}
2675#endif /* UNIX */
2676
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002677#if defined(VMS) && !defined(MIN)
2678/* Older DECC compiler for VAX doesn't define MIN() */
2679# define MIN(a, b) ((a) < (b) ? (a) : (b))
2680#endif
2681
Bram Moolenaar071d4272004-06-13 20:20:40 +00002682/*
Bram Moolenaar292ad192005-12-11 21:29:51 +00002683 * buf_write() - write to file "fname" lines "start" through "end"
Bram Moolenaar071d4272004-06-13 20:20:40 +00002684 *
2685 * We do our own buffering here because fwrite() is so slow.
2686 *
Bram Moolenaar292ad192005-12-11 21:29:51 +00002687 * If "forceit" is true, we don't care for errors when attempting backups.
2688 * In case of an error everything possible is done to restore the original
2689 * file. But when "forceit" is TRUE, we risk loosing it.
2690 *
2691 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
2692 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002693 *
2694 * This function must NOT use NameBuff (because it's called by autowrite()).
2695 *
2696 * return FAIL for failure, OK otherwise
2697 */
2698 int
2699buf_write(buf, fname, sfname, start, end, eap, append, forceit,
2700 reset_changed, filtering)
2701 buf_T *buf;
2702 char_u *fname;
2703 char_u *sfname;
2704 linenr_T start, end;
2705 exarg_T *eap; /* for forced 'ff' and 'fenc', can be
2706 NULL! */
Bram Moolenaar292ad192005-12-11 21:29:51 +00002707 int append; /* append to the file */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002708 int forceit;
2709 int reset_changed;
2710 int filtering;
2711{
2712 int fd;
2713 char_u *backup = NULL;
2714 int backup_copy = FALSE; /* copy the original file? */
2715 int dobackup;
2716 char_u *ffname;
2717 char_u *wfname = NULL; /* name of file to write to */
2718 char_u *s;
2719 char_u *ptr;
2720 char_u c;
2721 int len;
2722 linenr_T lnum;
2723 long nchars;
2724 char_u *errmsg = NULL;
2725 char_u *errnum = NULL;
2726 char_u *buffer;
2727 char_u smallbuf[SMBUFSIZE];
2728 char_u *backup_ext;
2729 int bufsize;
2730 long perm; /* file permissions */
2731 int retval = OK;
2732 int newfile = FALSE; /* TRUE if file doesn't exist yet */
2733 int msg_save = msg_scroll;
2734 int overwriting; /* TRUE if writing over original */
2735 int no_eol = FALSE; /* no end-of-line written */
2736 int device = FALSE; /* writing to a device */
2737 struct stat st_old;
2738 int prev_got_int = got_int;
2739 int file_readonly = FALSE; /* overwritten file is read-only */
2740 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
2741#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
2742 int made_writable = FALSE; /* 'w' bit has been set */
2743#endif
2744 /* writing everything */
2745 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
2746#ifdef FEAT_AUTOCMD
2747 linenr_T old_line_count = buf->b_ml.ml_line_count;
2748#endif
2749 int attr;
2750 int fileformat;
2751 int write_bin;
2752 struct bw_info write_info; /* info for buf_write_bytes() */
2753#ifdef FEAT_MBYTE
2754 int converted = FALSE;
2755 int notconverted = FALSE;
2756 char_u *fenc; /* effective 'fileencoding' */
2757 char_u *fenc_tofree = NULL; /* allocated "fenc" */
2758#endif
2759#ifdef HAS_BW_FLAGS
2760 int wb_flags = 0;
2761#endif
2762#ifdef HAVE_ACL
2763 vim_acl_T acl = NULL; /* ACL copied from original file to
2764 backup or new file */
2765#endif
2766
2767 if (fname == NULL || *fname == NUL) /* safety check */
2768 return FAIL;
2769
2770 /*
2771 * Disallow writing from .exrc and .vimrc in current directory for
2772 * security reasons.
2773 */
2774 if (check_secure())
2775 return FAIL;
2776
2777 /* Avoid a crash for a long name. */
2778 if (STRLEN(fname) >= MAXPATHL)
2779 {
2780 EMSG(_(e_longname));
2781 return FAIL;
2782 }
2783
2784#ifdef FEAT_MBYTE
2785 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
2786 write_info.bw_conv_buf = NULL;
2787 write_info.bw_conv_error = FALSE;
2788 write_info.bw_restlen = 0;
2789# ifdef USE_ICONV
2790 write_info.bw_iconv_fd = (iconv_t)-1;
2791# endif
2792#endif
2793
Bram Moolenaardf177f62005-02-22 08:39:57 +00002794 /* After writing a file changedtick changes but we don't want to display
2795 * the line. */
2796 ex_no_reprint = TRUE;
2797
Bram Moolenaar071d4272004-06-13 20:20:40 +00002798 /*
2799 * If there is no file name yet, use the one for the written file.
2800 * BF_NOTEDITED is set to reflect this (in case the write fails).
2801 * Don't do this when the write is for a filter command.
Bram Moolenaar292ad192005-12-11 21:29:51 +00002802 * Don't do this when appending.
2803 * Only do this when 'cpoptions' contains the 'F' flag.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002804 */
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002805 if (buf->b_ffname == NULL
2806 && reset_changed
Bram Moolenaar071d4272004-06-13 20:20:40 +00002807 && whole
2808 && buf == curbuf
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00002809#ifdef FEAT_QUICKFIX
2810 && !bt_nofile(buf)
2811#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002812 && !filtering
Bram Moolenaar292ad192005-12-11 21:29:51 +00002813 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002814 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
2815 {
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002816 if (set_rw_fname(fname, sfname) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002817 return FAIL;
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00002818 buf = curbuf; /* just in case autocmds made "buf" invalid */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002819 }
2820
2821 if (sfname == NULL)
2822 sfname = fname;
2823 /*
2824 * For Unix: Use the short file name whenever possible.
2825 * Avoids problems with networks and when directory names are changed.
2826 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
2827 * another directory, which we don't detect
2828 */
2829 ffname = fname; /* remember full fname */
2830#ifdef UNIX
2831 fname = sfname;
2832#endif
2833
2834 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
2835 overwriting = TRUE;
2836 else
2837 overwriting = FALSE;
2838
2839 if (exiting)
2840 settmode(TMODE_COOK); /* when exiting allow typahead now */
2841
2842 ++no_wait_return; /* don't wait for return yet */
2843
2844 /*
2845 * Set '[ and '] marks to the lines to be written.
2846 */
2847 buf->b_op_start.lnum = start;
2848 buf->b_op_start.col = 0;
2849 buf->b_op_end.lnum = end;
2850 buf->b_op_end.col = 0;
2851
2852#ifdef FEAT_AUTOCMD
2853 {
2854 aco_save_T aco;
2855 int buf_ffname = FALSE;
2856 int buf_sfname = FALSE;
2857 int buf_fname_f = FALSE;
2858 int buf_fname_s = FALSE;
2859 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002860 int nofile_err = FALSE;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002861 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002862
2863 /*
2864 * Apply PRE aucocommands.
2865 * Set curbuf to the buffer to be written.
2866 * Careful: The autocommands may call buf_write() recursively!
2867 */
2868 if (ffname == buf->b_ffname)
2869 buf_ffname = TRUE;
2870 if (sfname == buf->b_sfname)
2871 buf_sfname = TRUE;
2872 if (fname == buf->b_ffname)
2873 buf_fname_f = TRUE;
2874 if (fname == buf->b_sfname)
2875 buf_fname_s = TRUE;
2876
2877 /* set curwin/curbuf to buf and save a few things */
2878 aucmd_prepbuf(&aco, buf);
2879
2880 if (append)
2881 {
2882 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
2883 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002884 {
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00002885 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002886 nofile_err = TRUE;
2887 else
2888 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002890 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002891 }
2892 else if (filtering)
2893 {
2894 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
2895 NULL, sfname, FALSE, curbuf, eap);
2896 }
2897 else if (reset_changed && whole)
2898 {
2899 if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
2900 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002901 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00002902 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002903 nofile_err = TRUE;
2904 else
2905 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002906 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002907 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908 }
2909 else
2910 {
2911 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
2912 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002913 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00002914 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002915 nofile_err = TRUE;
2916 else
2917 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002919 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920 }
2921
2922 /* restore curwin/curbuf and a few other things */
2923 aucmd_restbuf(&aco);
2924
2925 /*
2926 * In three situations we return here and don't write the file:
2927 * 1. the autocommands deleted or unloaded the buffer.
2928 * 2. The autocommands abort script processing.
2929 * 3. If one of the "Cmd" autocommands was executed.
2930 */
2931 if (!buf_valid(buf))
2932 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002933 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar1e015462005-09-25 22:16:38 +00002934 || did_cmd || nofile_err
2935#ifdef FEAT_EVAL
2936 || aborting()
2937#endif
2938 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002939 {
2940 --no_wait_return;
2941 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002942 if (nofile_err)
2943 EMSG(_("E676: No matching autocommands for acwrite buffer"));
2944
Bram Moolenaar1e015462005-09-25 22:16:38 +00002945 if (nofile_err
2946#ifdef FEAT_EVAL
2947 || aborting()
2948#endif
2949 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002950 /* An aborting error, interrupt or exception in the
2951 * autocommands. */
2952 return FAIL;
2953 if (did_cmd)
2954 {
2955 if (buf == NULL)
2956 /* The buffer was deleted. We assume it was written
2957 * (can't retry anyway). */
2958 return OK;
2959 if (overwriting)
2960 {
2961 /* Assume the buffer was written, update the timestamp. */
2962 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00002963 if (append)
2964 buf->b_flags &= ~BF_NEW;
2965 else
2966 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002967 }
Bram Moolenaar292ad192005-12-11 21:29:51 +00002968 if (reset_changed && buf->b_changed && !append
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00002969 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002970 /* Buffer still changed, the autocommands didn't work
2971 * properly. */
2972 return FAIL;
2973 return OK;
2974 }
2975#ifdef FEAT_EVAL
2976 if (!aborting())
2977#endif
2978 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
2979 return FAIL;
2980 }
2981
2982 /*
2983 * The autocommands may have changed the number of lines in the file.
2984 * When writing the whole file, adjust the end.
2985 * When writing part of the file, assume that the autocommands only
2986 * changed the number of lines that are to be written (tricky!).
2987 */
2988 if (buf->b_ml.ml_line_count != old_line_count)
2989 {
2990 if (whole) /* write all */
2991 end = buf->b_ml.ml_line_count;
2992 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
2993 end += buf->b_ml.ml_line_count - old_line_count;
2994 else /* less lines */
2995 {
2996 end -= old_line_count - buf->b_ml.ml_line_count;
2997 if (end < start)
2998 {
2999 --no_wait_return;
3000 msg_scroll = msg_save;
3001 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
3002 return FAIL;
3003 }
3004 }
3005 }
3006
3007 /*
3008 * The autocommands may have changed the name of the buffer, which may
3009 * be kept in fname, ffname and sfname.
3010 */
3011 if (buf_ffname)
3012 ffname = buf->b_ffname;
3013 if (buf_sfname)
3014 sfname = buf->b_sfname;
3015 if (buf_fname_f)
3016 fname = buf->b_ffname;
3017 if (buf_fname_s)
3018 fname = buf->b_sfname;
3019 }
3020#endif
3021
3022#ifdef FEAT_NETBEANS_INTG
3023 if (usingNetbeans && isNetbeansBuffer(buf))
3024 {
3025 if (whole)
3026 {
3027 /*
3028 * b_changed can be 0 after an undo, but we still need to write
3029 * the buffer to NetBeans.
3030 */
3031 if (buf->b_changed || isNetbeansModified(buf))
3032 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00003033 --no_wait_return; /* may wait for return now */
3034 msg_scroll = msg_save;
3035 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003036 return retval;
3037 }
3038 else
3039 {
3040 errnum = (char_u *)"E656: ";
3041 errmsg = (char_u *)_("NetBeans dissallows writes of unmodified buffers");
3042 buffer = NULL;
3043 goto fail;
3044 }
3045 }
3046 else
3047 {
3048 errnum = (char_u *)"E657: ";
3049 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
3050 buffer = NULL;
3051 goto fail;
3052 }
3053 }
3054#endif
3055
3056 if (shortmess(SHM_OVER) && !exiting)
3057 msg_scroll = FALSE; /* overwrite previous file message */
3058 else
3059 msg_scroll = TRUE; /* don't overwrite previous file message */
3060 if (!filtering)
3061 filemess(buf,
3062#ifndef UNIX
3063 sfname,
3064#else
3065 fname,
3066#endif
3067 (char_u *)"", 0); /* show that we are busy */
3068 msg_scroll = FALSE; /* always overwrite the file message now */
3069
3070 buffer = alloc(BUFSIZE);
3071 if (buffer == NULL) /* can't allocate big buffer, use small
3072 * one (to be able to write when out of
3073 * memory) */
3074 {
3075 buffer = smallbuf;
3076 bufsize = SMBUFSIZE;
3077 }
3078 else
3079 bufsize = BUFSIZE;
3080
3081 /*
3082 * Get information about original file (if there is one).
3083 */
3084#if defined(UNIX) && !defined(ARCHIE)
3085 st_old.st_dev = st_old.st_ino = 0;
3086 perm = -1;
3087 if (mch_stat((char *)fname, &st_old) < 0)
3088 newfile = TRUE;
3089 else
3090 {
3091 perm = st_old.st_mode;
3092 if (!S_ISREG(st_old.st_mode)) /* not a file */
3093 {
3094 if (S_ISDIR(st_old.st_mode))
3095 {
3096 errnum = (char_u *)"E502: ";
3097 errmsg = (char_u *)_("is a directory");
3098 goto fail;
3099 }
3100 if (mch_nodetype(fname) != NODE_WRITABLE)
3101 {
3102 errnum = (char_u *)"E503: ";
3103 errmsg = (char_u *)_("is not a file or writable device");
3104 goto fail;
3105 }
3106 /* It's a device of some kind (or a fifo) which we can write to
3107 * but for which we can't make a backup. */
3108 device = TRUE;
3109 newfile = TRUE;
3110 perm = -1;
3111 }
3112 }
3113#else /* !UNIX */
3114 /*
3115 * Check for a writable device name.
3116 */
3117 c = mch_nodetype(fname);
3118 if (c == NODE_OTHER)
3119 {
3120 errnum = (char_u *)"E503: ";
3121 errmsg = (char_u *)_("is not a file or writable device");
3122 goto fail;
3123 }
3124 if (c == NODE_WRITABLE)
3125 {
3126 device = TRUE;
3127 newfile = TRUE;
3128 perm = -1;
3129 }
3130 else
3131 {
3132 perm = mch_getperm(fname);
3133 if (perm < 0)
3134 newfile = TRUE;
3135 else if (mch_isdir(fname))
3136 {
3137 errnum = (char_u *)"E502: ";
3138 errmsg = (char_u *)_("is a directory");
3139 goto fail;
3140 }
3141 if (overwriting)
3142 (void)mch_stat((char *)fname, &st_old);
3143 }
3144#endif /* !UNIX */
3145
3146 if (!device && !newfile)
3147 {
3148 /*
3149 * Check if the file is really writable (when renaming the file to
3150 * make a backup we won't discover it later).
3151 */
3152 file_readonly = (
3153# ifdef USE_MCH_ACCESS
3154# ifdef UNIX
3155 (perm & 0222) == 0 ||
3156# endif
3157 mch_access((char *)fname, W_OK)
3158# else
3159 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
3160 ? TRUE : (close(fd), FALSE)
3161# endif
3162 );
3163 if (!forceit && file_readonly)
3164 {
3165 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3166 {
3167 errnum = (char_u *)"E504: ";
3168 errmsg = (char_u *)_(err_readonly);
3169 }
3170 else
3171 {
3172 errnum = (char_u *)"E505: ";
3173 errmsg = (char_u *)_("is read-only (add ! to override)");
3174 }
3175 goto fail;
3176 }
3177
3178 /*
3179 * Check if the timestamp hasn't changed since reading the file.
3180 */
3181 if (overwriting)
3182 {
3183 retval = check_mtime(buf, &st_old);
3184 if (retval == FAIL)
3185 goto fail;
3186 }
3187 }
3188
3189#ifdef HAVE_ACL
3190 /*
3191 * For systems that support ACL: get the ACL from the original file.
3192 */
3193 if (!newfile)
3194 acl = mch_get_acl(fname);
3195#endif
3196
3197 /*
3198 * If 'backupskip' is not empty, don't make a backup for some files.
3199 */
3200 dobackup = (p_wb || p_bk || *p_pm != NUL);
3201#ifdef FEAT_WILDIGN
3202 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3203 dobackup = FALSE;
3204#endif
3205
3206 /*
3207 * Save the value of got_int and reset it. We don't want a previous
3208 * interruption cancel writing, only hitting CTRL-C while writing should
3209 * abort it.
3210 */
3211 prev_got_int = got_int;
3212 got_int = FALSE;
3213
3214 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3215 buf->b_saving = TRUE;
3216
3217 /*
3218 * If we are not appending or filtering, the file exists, and the
3219 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3220 * When 'patchmode' is set also make a backup when appending.
3221 *
3222 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3223 * off. This helps when editing large files on almost-full disks.
3224 */
3225 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3226 {
3227#if defined(UNIX) || defined(WIN32)
3228 struct stat st;
3229#endif
3230
3231 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3232 backup_copy = TRUE;
3233#if defined(UNIX) || defined(WIN32)
3234 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3235 {
3236 int i;
3237
3238# ifdef UNIX
3239 /*
3240 * Don't rename the file when:
3241 * - it's a hard link
3242 * - it's a symbolic link
3243 * - we don't have write permission in the directory
3244 * - we can't set the owner/group of the new file
3245 */
3246 if (st_old.st_nlink > 1
3247 || mch_lstat((char *)fname, &st) < 0
3248 || st.st_dev != st_old.st_dev
Bram Moolenaara5792f52005-11-23 21:25:05 +00003249 || st.st_ino != st_old.st_ino
3250# ifndef HAVE_FCHOWN
3251 || st.st_uid != st_old.st_uid
3252 || st.st_gid != st_old.st_gid
3253# endif
3254 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00003255 backup_copy = TRUE;
3256 else
3257# endif
3258 {
3259 /*
3260 * Check if we can create a file and set the owner/group to
3261 * the ones from the original file.
3262 * First find a file name that doesn't exist yet (use some
3263 * arbitrary numbers).
3264 */
3265 STRCPY(IObuff, fname);
3266 for (i = 4913; ; i += 123)
3267 {
3268 sprintf((char *)gettail(IObuff), "%d", i);
Bram Moolenaara5792f52005-11-23 21:25:05 +00003269 if (mch_lstat((char *)IObuff, &st) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003270 break;
3271 }
Bram Moolenaara5792f52005-11-23 21:25:05 +00003272 fd = mch_open((char *)IObuff,
3273 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274 if (fd < 0) /* can't write in directory */
3275 backup_copy = TRUE;
3276 else
3277 {
3278# ifdef UNIX
Bram Moolenaara5792f52005-11-23 21:25:05 +00003279# ifdef HAVE_FCHOWN
3280 fchown(fd, st_old.st_uid, st_old.st_gid);
3281# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282 if (mch_stat((char *)IObuff, &st) < 0
3283 || st.st_uid != st_old.st_uid
3284 || st.st_gid != st_old.st_gid
3285 || st.st_mode != perm)
3286 backup_copy = TRUE;
3287# endif
Bram Moolenaar98358622005-11-28 22:58:23 +00003288 /* Close the file before removing it, on MS-Windows we
3289 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003290 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003291 mch_remove(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003292 }
3293 }
3294 }
3295
3296# ifdef UNIX
3297 /*
3298 * Break symlinks and/or hardlinks if we've been asked to.
3299 */
3300 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3301 {
3302 int lstat_res;
3303
3304 lstat_res = mch_lstat((char *)fname, &st);
3305
3306 /* Symlinks. */
3307 if ((bkc_flags & BKC_BREAKSYMLINK)
3308 && lstat_res == 0
3309 && st.st_ino != st_old.st_ino)
3310 backup_copy = FALSE;
3311
3312 /* Hardlinks. */
3313 if ((bkc_flags & BKC_BREAKHARDLINK)
3314 && st_old.st_nlink > 1
3315 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3316 backup_copy = FALSE;
3317 }
3318#endif
3319
3320#endif
3321
3322 /* make sure we have a valid backup extension to use */
3323 if (*p_bex == NUL)
3324 {
3325#ifdef RISCOS
3326 backup_ext = (char_u *)"/bak";
3327#else
3328 backup_ext = (char_u *)".bak";
3329#endif
3330 }
3331 else
3332 backup_ext = p_bex;
3333
3334 if (backup_copy
3335 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3336 {
3337 int bfd;
3338 char_u *copybuf, *wp;
3339 int some_error = FALSE;
3340 struct stat st_new;
3341 char_u *dirp;
3342 char_u *rootname;
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003343#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003344 int did_set_shortname;
3345#endif
3346
3347 copybuf = alloc(BUFSIZE + 1);
3348 if (copybuf == NULL)
3349 {
3350 some_error = TRUE; /* out of memory */
3351 goto nobackup;
3352 }
3353
3354 /*
3355 * Try to make the backup in each directory in the 'bdir' option.
3356 *
3357 * Unix semantics has it, that we may have a writable file,
3358 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3359 * - the directory is not writable,
3360 * - the file may be a symbolic link,
3361 * - the file may belong to another user/group, etc.
3362 *
3363 * For these reasons, the existing writable file must be truncated
3364 * and reused. Creation of a backup COPY will be attempted.
3365 */
3366 dirp = p_bdir;
3367 while (*dirp)
3368 {
3369#ifdef UNIX
3370 st_new.st_ino = 0;
3371 st_new.st_dev = 0;
3372 st_new.st_gid = 0;
3373#endif
3374
3375 /*
3376 * Isolate one directory name, using an entry in 'bdir'.
3377 */
3378 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3379 rootname = get_file_in_dir(fname, copybuf);
3380 if (rootname == NULL)
3381 {
3382 some_error = TRUE; /* out of memory */
3383 goto nobackup;
3384 }
3385
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003386#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003387 did_set_shortname = FALSE;
3388#endif
3389
3390 /*
3391 * May try twice if 'shortname' not set.
3392 */
3393 for (;;)
3394 {
3395 /*
3396 * Make backup file name.
3397 */
3398 backup = buf_modname(
3399#ifdef SHORT_FNAME
3400 TRUE,
3401#else
3402 (buf->b_p_sn || buf->b_shortname),
3403#endif
3404 rootname, backup_ext, FALSE);
3405 if (backup == NULL)
3406 {
3407 vim_free(rootname);
3408 some_error = TRUE; /* out of memory */
3409 goto nobackup;
3410 }
3411
3412 /*
3413 * Check if backup file already exists.
3414 */
3415 if (mch_stat((char *)backup, &st_new) >= 0)
3416 {
3417#ifdef UNIX
3418 /*
3419 * Check if backup file is same as original file.
3420 * May happen when modname() gave the same file back.
3421 * E.g. silly link, or file name-length reached.
3422 * If we don't check here, we either ruin the file
3423 * when copying or erase it after writing. jw.
3424 */
3425 if (st_new.st_dev == st_old.st_dev
3426 && st_new.st_ino == st_old.st_ino)
3427 {
3428 vim_free(backup);
3429 backup = NULL; /* no backup file to delete */
3430# ifndef SHORT_FNAME
3431 /*
3432 * may try again with 'shortname' set
3433 */
3434 if (!(buf->b_shortname || buf->b_p_sn))
3435 {
3436 buf->b_shortname = TRUE;
3437 did_set_shortname = TRUE;
3438 continue;
3439 }
3440 /* setting shortname didn't help */
3441 if (did_set_shortname)
3442 buf->b_shortname = FALSE;
3443# endif
3444 break;
3445 }
3446#endif
3447
3448 /*
3449 * If we are not going to keep the backup file, don't
3450 * delete an existing one, try to use another name.
3451 * Change one character, just before the extension.
3452 */
3453 if (!p_bk)
3454 {
3455 wp = backup + STRLEN(backup) - 1
3456 - STRLEN(backup_ext);
3457 if (wp < backup) /* empty file name ??? */
3458 wp = backup;
3459 *wp = 'z';
3460 while (*wp > 'a'
3461 && mch_stat((char *)backup, &st_new) >= 0)
3462 --*wp;
3463 /* They all exist??? Must be something wrong. */
3464 if (*wp == 'a')
3465 {
3466 vim_free(backup);
3467 backup = NULL;
3468 }
3469 }
3470 }
3471 break;
3472 }
3473 vim_free(rootname);
3474
3475 /*
3476 * Try to create the backup file
3477 */
3478 if (backup != NULL)
3479 {
3480 /* remove old backup, if present */
3481 mch_remove(backup);
3482 /* Open with O_EXCL to avoid the file being created while
3483 * we were sleeping (symlink hacker attack?) */
3484 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00003485 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
3486 perm & 0777);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003487 if (bfd < 0)
3488 {
3489 vim_free(backup);
3490 backup = NULL;
3491 }
3492 else
3493 {
3494 /* set file protection same as original file, but
3495 * strip s-bit */
3496 (void)mch_setperm(backup, perm & 0777);
3497
3498#ifdef UNIX
3499 /*
3500 * Try to set the group of the backup same as the
3501 * original file. If this fails, set the protection
3502 * bits for the group same as the protection bits for
3503 * others.
3504 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003505 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00003506# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003507 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003508# endif
3509 )
3510 mch_setperm(backup,
3511 (perm & 0707) | ((perm & 07) << 3));
3512#endif
3513
3514 /*
3515 * copy the file.
3516 */
3517 write_info.bw_fd = bfd;
3518 write_info.bw_buf = copybuf;
3519#ifdef HAS_BW_FLAGS
3520 write_info.bw_flags = FIO_NOCONVERT;
3521#endif
3522 while ((write_info.bw_len = vim_read(fd, copybuf,
3523 BUFSIZE)) > 0)
3524 {
3525 if (buf_write_bytes(&write_info) == FAIL)
3526 {
3527 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3528 break;
3529 }
3530 ui_breakcheck();
3531 if (got_int)
3532 {
3533 errmsg = (char_u *)_(e_interr);
3534 break;
3535 }
3536 }
3537
3538 if (close(bfd) < 0 && errmsg == NULL)
3539 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3540 if (write_info.bw_len < 0)
3541 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3542#ifdef UNIX
3543 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3544#endif
3545#ifdef HAVE_ACL
3546 mch_set_acl(backup, acl);
3547#endif
3548 break;
3549 }
3550 }
3551 }
3552 nobackup:
3553 close(fd); /* ignore errors for closing read file */
3554 vim_free(copybuf);
3555
3556 if (backup == NULL && errmsg == NULL)
3557 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3558 /* ignore errors when forceit is TRUE */
3559 if ((some_error || errmsg != NULL) && !forceit)
3560 {
3561 retval = FAIL;
3562 goto fail;
3563 }
3564 errmsg = NULL;
3565 }
3566 else
3567 {
3568 char_u *dirp;
3569 char_u *p;
3570 char_u *rootname;
3571
3572 /*
3573 * Make a backup by renaming the original file.
3574 */
3575 /*
3576 * If 'cpoptions' includes the "W" flag, we don't want to
3577 * overwrite a read-only file. But rename may be possible
3578 * anyway, thus we need an extra check here.
3579 */
3580 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3581 {
3582 errnum = (char_u *)"E504: ";
3583 errmsg = (char_u *)_(err_readonly);
3584 goto fail;
3585 }
3586
3587 /*
3588 *
3589 * Form the backup file name - change path/fo.o.h to
3590 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3591 * that works is used.
3592 */
3593 dirp = p_bdir;
3594 while (*dirp)
3595 {
3596 /*
3597 * Isolate one directory name and make the backup file name.
3598 */
3599 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3600 rootname = get_file_in_dir(fname, IObuff);
3601 if (rootname == NULL)
3602 backup = NULL;
3603 else
3604 {
3605 backup = buf_modname(
3606#ifdef SHORT_FNAME
3607 TRUE,
3608#else
3609 (buf->b_p_sn || buf->b_shortname),
3610#endif
3611 rootname, backup_ext, FALSE);
3612 vim_free(rootname);
3613 }
3614
3615 if (backup != NULL)
3616 {
3617 /*
3618 * If we are not going to keep the backup file, don't
3619 * delete an existing one, try to use another name.
3620 * Change one character, just before the extension.
3621 */
3622 if (!p_bk && mch_getperm(backup) >= 0)
3623 {
3624 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3625 if (p < backup) /* empty file name ??? */
3626 p = backup;
3627 *p = 'z';
3628 while (*p > 'a' && mch_getperm(backup) >= 0)
3629 --*p;
3630 /* They all exist??? Must be something wrong! */
3631 if (*p == 'a')
3632 {
3633 vim_free(backup);
3634 backup = NULL;
3635 }
3636 }
3637 }
3638 if (backup != NULL)
3639 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003640 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00003641 * Delete any existing backup and move the current version
3642 * to the backup. For safety, we don't remove the backup
3643 * until the write has finished successfully. And if the
3644 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003645 */
3646 /*
3647 * If the renaming of the original file to the backup file
3648 * works, quit here.
3649 */
3650 if (vim_rename(fname, backup) == 0)
3651 break;
3652
3653 vim_free(backup); /* don't do the rename below */
3654 backup = NULL;
3655 }
3656 }
3657 if (backup == NULL && !forceit)
3658 {
3659 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3660 goto fail;
3661 }
3662 }
3663 }
3664
3665#if defined(UNIX) && !defined(ARCHIE)
3666 /* When using ":w!" and the file was read-only: make it writable */
3667 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3668 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3669 {
3670 perm |= 0200;
3671 (void)mch_setperm(fname, perm);
3672 made_writable = TRUE;
3673 }
3674#endif
3675
3676 /* When using ":w!" and writing to the current file, readonly makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003677 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
3678 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003679 {
3680 buf->b_p_ro = FALSE;
3681#ifdef FEAT_TITLE
3682 need_maketitle = TRUE; /* set window title later */
3683#endif
3684#ifdef FEAT_WINDOWS
3685 status_redraw_all(); /* redraw status lines later */
3686#endif
3687 }
3688
3689 if (end > buf->b_ml.ml_line_count)
3690 end = buf->b_ml.ml_line_count;
3691 if (buf->b_ml.ml_flags & ML_EMPTY)
3692 start = end + 1;
3693
3694 /*
3695 * If the original file is being overwritten, there is a small chance that
3696 * we crash in the middle of writing. Therefore the file is preserved now.
3697 * This makes all block numbers positive so that recovery does not need
3698 * the original file.
3699 * Don't do this if there is a backup file and we are exiting.
3700 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003701 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00003702 && !(exiting && backup != NULL))
3703 {
3704 ml_preserve(buf, FALSE);
3705 if (got_int)
3706 {
3707 errmsg = (char_u *)_(e_interr);
3708 goto restore_backup;
3709 }
3710 }
3711
3712#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
3713 /*
3714 * Before risking to lose the original file verify if there's
3715 * a resource fork to preserve, and if cannot be done warn
3716 * the users. This happens when overwriting without backups.
3717 */
3718 if (backup == NULL && overwriting && !append)
3719 if (mch_has_resource_fork(fname))
3720 {
3721 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
3722 goto restore_backup;
3723 }
3724#endif
3725
3726#ifdef VMS
3727 vms_remove_version(fname); /* remove version */
3728#endif
3729 /* Default: write the the file directly. May write to a temp file for
3730 * multi-byte conversion. */
3731 wfname = fname;
3732
3733#ifdef FEAT_MBYTE
3734 /* Check for forced 'fileencoding' from "++opt=val" argument. */
3735 if (eap != NULL && eap->force_enc != 0)
3736 {
3737 fenc = eap->cmd + eap->force_enc;
3738 fenc = enc_canonize(fenc);
3739 fenc_tofree = fenc;
3740 }
3741 else
3742 fenc = buf->b_p_fenc;
3743
3744 /*
3745 * The file needs to be converted when 'fileencoding' is set and
3746 * 'fileencoding' differs from 'encoding'.
3747 */
3748 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
3749
3750 /*
3751 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3752 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3753 * Prepare the flags for it and allocate bw_conv_buf when needed.
3754 */
3755 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
3756 {
3757 wb_flags = get_fio_flags(fenc);
3758 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
3759 {
3760 /* Need to allocate a buffer to translate into. */
3761 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
3762 write_info.bw_conv_buflen = bufsize * 2;
3763 else /* FIO_UCS4 */
3764 write_info.bw_conv_buflen = bufsize * 4;
3765 write_info.bw_conv_buf
3766 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3767 if (write_info.bw_conv_buf == NULL)
3768 end = 0;
3769 }
3770 }
3771
3772# ifdef WIN3264
3773 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
3774 {
3775 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
3776 write_info.bw_conv_buflen = bufsize * 4;
3777 write_info.bw_conv_buf
3778 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3779 if (write_info.bw_conv_buf == NULL)
3780 end = 0;
3781 }
3782# endif
3783
3784# ifdef MACOS_X
3785 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
3786 {
3787 write_info.bw_conv_buflen = bufsize * 3;
3788 write_info.bw_conv_buf
3789 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3790 if (write_info.bw_conv_buf == NULL)
3791 end = 0;
3792 }
3793# endif
3794
3795# if defined(FEAT_EVAL) || defined(USE_ICONV)
3796 if (converted && wb_flags == 0)
3797 {
3798# ifdef USE_ICONV
3799 /*
3800 * Use iconv() conversion when conversion is needed and it's not done
3801 * internally.
3802 */
3803 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3804 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3805 if (write_info.bw_iconv_fd != (iconv_t)-1)
3806 {
3807 /* We're going to use iconv(), allocate a buffer to convert in. */
3808 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3809 write_info.bw_conv_buf
3810 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3811 if (write_info.bw_conv_buf == NULL)
3812 end = 0;
3813 write_info.bw_first = TRUE;
3814 }
3815# ifdef FEAT_EVAL
3816 else
3817# endif
3818# endif
3819
3820# ifdef FEAT_EVAL
3821 /*
3822 * When the file needs to be converted with 'charconvert' after
3823 * writing, write to a temp file instead and let the conversion
3824 * overwrite the original file.
3825 */
3826 if (*p_ccv != NUL)
3827 {
3828 wfname = vim_tempname('w');
3829 if (wfname == NULL) /* Can't write without a tempfile! */
3830 {
3831 errmsg = (char_u *)_("E214: Can't find temp file for writing");
3832 goto restore_backup;
3833 }
3834 }
3835# endif
3836 }
3837# endif
3838 if (converted && wb_flags == 0
3839# ifdef USE_ICONV
3840 && write_info.bw_iconv_fd == (iconv_t)-1
3841# endif
3842# ifdef FEAT_EVAL
3843 && wfname == fname
3844# endif
3845 )
3846 {
3847 if (!forceit)
3848 {
3849 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
3850 goto restore_backup;
3851 }
3852 notconverted = TRUE;
3853 }
3854#endif
3855
3856 /*
3857 * Open the file "wfname" for writing.
3858 * We may try to open the file twice: If we can't write to the
3859 * file and forceit is TRUE we delete the existing file and try to create
3860 * a new one. If this still fails we may have lost the original file!
3861 * (this may happen when the user reached his quotum for number of files).
3862 * Appending will fail if the file does not exist and forceit is FALSE.
3863 */
3864 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
3865 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3866 : (O_CREAT | O_TRUNC))
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00003867 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003868 {
3869 /*
3870 * A forced write will try to create a new file if the old one is
3871 * still readonly. This may also happen when the directory is
3872 * read-only. In that case the mch_remove() will fail.
3873 */
3874 if (errmsg == NULL)
3875 {
3876#ifdef UNIX
3877 struct stat st;
3878
3879 /* Don't delete the file when it's a hard or symbolic link. */
3880 if ((!newfile && st_old.st_nlink > 1)
3881 || (mch_lstat((char *)fname, &st) == 0
3882 && (st.st_dev != st_old.st_dev
3883 || st.st_ino != st_old.st_ino)))
3884 errmsg = (char_u *)_("E166: Can't open linked file for writing");
3885 else
3886#endif
3887 {
3888 errmsg = (char_u *)_("E212: Can't open file for writing");
3889 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
3890 && perm >= 0)
3891 {
3892#ifdef UNIX
3893 /* we write to the file, thus it should be marked
3894 writable after all */
3895 if (!(perm & 0200))
3896 made_writable = TRUE;
3897 perm |= 0200;
3898 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
3899 perm &= 0777;
3900#endif
3901 if (!append) /* don't remove when appending */
3902 mch_remove(wfname);
3903 continue;
3904 }
3905 }
3906 }
3907
3908restore_backup:
3909 {
3910 struct stat st;
3911
3912 /*
3913 * If we failed to open the file, we don't need a backup. Throw it
3914 * away. If we moved or removed the original file try to put the
3915 * backup in its place.
3916 */
3917 if (backup != NULL && wfname == fname)
3918 {
3919 if (backup_copy)
3920 {
3921 /*
3922 * There is a small chance that we removed the original,
3923 * try to move the copy in its place.
3924 * This may not work if the vim_rename() fails.
3925 * In that case we leave the copy around.
3926 */
3927 /* If file does not exist, put the copy in its place */
3928 if (mch_stat((char *)fname, &st) < 0)
3929 vim_rename(backup, fname);
3930 /* if original file does exist throw away the copy */
3931 if (mch_stat((char *)fname, &st) >= 0)
3932 mch_remove(backup);
3933 }
3934 else
3935 {
3936 /* try to put the original file back */
3937 vim_rename(backup, fname);
3938 }
3939 }
3940
3941 /* if original file no longer exists give an extra warning */
3942 if (!newfile && mch_stat((char *)fname, &st) < 0)
3943 end = 0;
3944 }
3945
3946#ifdef FEAT_MBYTE
3947 if (wfname != fname)
3948 vim_free(wfname);
3949#endif
3950 goto fail;
3951 }
3952 errmsg = NULL;
3953
3954#if defined(MACOS_CLASSIC) || defined(WIN3264)
3955 /* TODO: Is it need for MACOS_X? (Dany) */
3956 /*
3957 * On macintosh copy the original files attributes (i.e. the backup)
3958 * This is done in order to preserve the ressource fork and the
3959 * Finder attribute (label, comments, custom icons, file creatore)
3960 */
3961 if (backup != NULL && overwriting && !append)
3962 {
3963 if (backup_copy)
3964 (void)mch_copy_file_attribute(wfname, backup);
3965 else
3966 (void)mch_copy_file_attribute(backup, wfname);
3967 }
3968
3969 if (!overwriting && !append)
3970 {
3971 if (buf->b_ffname != NULL)
3972 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
3973 /* Should copy ressource fork */
3974 }
3975#endif
3976
3977 write_info.bw_fd = fd;
3978
3979#ifdef FEAT_CRYPT
3980 if (*buf->b_p_key && !filtering)
3981 {
3982 crypt_init_keys(buf->b_p_key);
3983 /* Write magic number, so that Vim knows that this file is encrypted
3984 * when reading it again. This also undergoes utf-8 to ucs-2/4
3985 * conversion when needed. */
3986 write_info.bw_buf = (char_u *)CRYPT_MAGIC;
3987 write_info.bw_len = CRYPT_MAGIC_LEN;
3988 write_info.bw_flags = FIO_NOCONVERT;
3989 if (buf_write_bytes(&write_info) == FAIL)
3990 end = 0;
3991 wb_flags |= FIO_ENCRYPTED;
3992 }
3993#endif
3994
3995 write_info.bw_buf = buffer;
3996 nchars = 0;
3997
3998 /* use "++bin", "++nobin" or 'binary' */
3999 if (eap != NULL && eap->force_bin != 0)
4000 write_bin = (eap->force_bin == FORCE_BIN);
4001 else
4002 write_bin = buf->b_p_bin;
4003
4004#ifdef FEAT_MBYTE
4005 /*
4006 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004007 * Skip it when appending and the file already existed, the BOM only makes
4008 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004009 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004010 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004011 {
4012 write_info.bw_len = make_bom(buffer, fenc);
4013 if (write_info.bw_len > 0)
4014 {
4015 /* don't convert, do encryption */
4016 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
4017 if (buf_write_bytes(&write_info) == FAIL)
4018 end = 0;
4019 else
4020 nchars += write_info.bw_len;
4021 }
4022 }
4023#endif
4024
4025 write_info.bw_len = bufsize;
4026#ifdef HAS_BW_FLAGS
4027 write_info.bw_flags = wb_flags;
4028#endif
4029 fileformat = get_fileformat_force(buf, eap);
4030 s = buffer;
4031 len = 0;
4032 for (lnum = start; lnum <= end; ++lnum)
4033 {
4034 /*
4035 * The next while loop is done once for each character written.
4036 * Keep it fast!
4037 */
4038 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
4039 while ((c = *++ptr) != NUL)
4040 {
4041 if (c == NL)
4042 *s = NUL; /* replace newlines with NULs */
4043 else if (c == CAR && fileformat == EOL_MAC)
4044 *s = NL; /* Mac: replace CRs with NLs */
4045 else
4046 *s = c;
4047 ++s;
4048 if (++len != bufsize)
4049 continue;
4050 if (buf_write_bytes(&write_info) == FAIL)
4051 {
4052 end = 0; /* write error: break loop */
4053 break;
4054 }
4055 nchars += bufsize;
4056 s = buffer;
4057 len = 0;
4058 }
4059 /* write failed or last line has no EOL: stop here */
4060 if (end == 0
4061 || (lnum == end
4062 && write_bin
4063 && (lnum == write_no_eol_lnum
4064 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
4065 {
4066 ++lnum; /* written the line, count it */
4067 no_eol = TRUE;
4068 break;
4069 }
4070 if (fileformat == EOL_UNIX)
4071 *s++ = NL;
4072 else
4073 {
4074 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
4075 if (fileformat == EOL_DOS) /* write CR-NL */
4076 {
4077 if (++len == bufsize)
4078 {
4079 if (buf_write_bytes(&write_info) == FAIL)
4080 {
4081 end = 0; /* write error: break loop */
4082 break;
4083 }
4084 nchars += bufsize;
4085 s = buffer;
4086 len = 0;
4087 }
4088 *s++ = NL;
4089 }
4090 }
4091 if (++len == bufsize && end)
4092 {
4093 if (buf_write_bytes(&write_info) == FAIL)
4094 {
4095 end = 0; /* write error: break loop */
4096 break;
4097 }
4098 nchars += bufsize;
4099 s = buffer;
4100 len = 0;
4101
4102 ui_breakcheck();
4103 if (got_int)
4104 {
4105 end = 0; /* Interrupted, break loop */
4106 break;
4107 }
4108 }
4109#ifdef VMS
4110 /*
4111 * On VMS there is a problem: newlines get added when writing blocks
4112 * at a time. Fix it by writing a line at a time.
4113 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004114 * Explanation: VAX/DECC RTL insists that records in some RMS
4115 * structures end with a newline (carriage return) character, and if
4116 * they don't it adds one.
4117 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004118 */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004119 if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004120 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004121 int b2write;
4122
4123 buf->b_fab_mrs = (buf->b_fab_mrs == 0
4124 ? MIN(4096, bufsize)
4125 : MIN(buf->b_fab_mrs, bufsize));
4126
4127 b2write = len;
4128 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004129 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00004130 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
4131 if (buf_write_bytes(&write_info) == FAIL)
4132 {
4133 end = 0;
4134 break;
4135 }
4136 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004137 }
4138 write_info.bw_len = bufsize;
4139 nchars += len;
4140 s = buffer;
4141 len = 0;
4142 }
4143#endif
4144 }
4145 if (len > 0 && end > 0)
4146 {
4147 write_info.bw_len = len;
4148 if (buf_write_bytes(&write_info) == FAIL)
4149 end = 0; /* write error */
4150 nchars += len;
4151 }
4152
4153#if defined(UNIX) && defined(HAVE_FSYNC)
4154 /* On many journalling file systems there is a bug that causes both the
4155 * original and the backup file to be lost when halting the system right
4156 * after writing the file. That's because only the meta-data is
4157 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004158 * been written to disk and we don't lose it.
4159 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004160 * (could be a pipe).
4161 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
4162 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004163 {
4164 errmsg = (char_u *)_("E667: Fsync failed");
4165 end = 0;
4166 }
4167#endif
4168
Bram Moolenaara5792f52005-11-23 21:25:05 +00004169#ifdef UNIX
4170 /* When creating a new file, set its owner/group to that of the original
4171 * file. Get the new device and inode number. */
4172 if (backup != NULL && !backup_copy)
4173 {
4174# ifdef HAVE_FCHOWN
4175 struct stat st;
4176
4177 /* don't change the owner when it's already OK, some systems remove
4178 * permission or ACL stuff */
4179 if (mch_stat((char *)wfname, &st) < 0
4180 || st.st_uid != st_old.st_uid
4181 || st.st_gid != st_old.st_gid)
4182 {
4183 fchown(fd, st_old.st_uid, st_old.st_gid);
4184 if (perm >= 0) /* set permission again, may have changed */
4185 (void)mch_setperm(wfname, perm);
4186 }
4187# endif
4188 buf_setino(buf);
4189 }
Bram Moolenaar8fa04452005-12-23 22:13:51 +00004190 else if (buf->b_dev < 0)
4191 /* Set the inode when creating a new file. */
4192 buf_setino(buf);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004193#endif
4194
Bram Moolenaar071d4272004-06-13 20:20:40 +00004195 if (close(fd) != 0)
4196 {
4197 errmsg = (char_u *)_("E512: Close failed");
4198 end = 0;
4199 }
4200
4201#ifdef UNIX
4202 if (made_writable)
4203 perm &= ~0200; /* reset 'w' bit for security reasons */
4204#endif
4205 if (perm >= 0) /* set perm. of new file same as old file */
4206 (void)mch_setperm(wfname, perm);
4207#ifdef RISCOS
4208 if (!append && !filtering)
4209 /* Set the filetype after writing the file. */
4210 mch_set_filetype(wfname, buf->b_p_oft);
4211#endif
4212#ifdef HAVE_ACL
4213 /* Probably need to set the ACL before changing the user (can't set the
4214 * ACL on a file the user doesn't own). */
4215 if (!backup_copy)
4216 mch_set_acl(wfname, acl);
4217#endif
4218
Bram Moolenaar071d4272004-06-13 20:20:40 +00004219
4220#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4221 if (wfname != fname)
4222 {
4223 /*
4224 * The file was written to a temp file, now it needs to be converted
4225 * with 'charconvert' to (overwrite) the output file.
4226 */
4227 if (end != 0)
4228 {
4229 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4230 wfname, fname) == FAIL)
4231 {
4232 write_info.bw_conv_error = TRUE;
4233 end = 0;
4234 }
4235 }
4236 mch_remove(wfname);
4237 vim_free(wfname);
4238 }
4239#endif
4240
4241 if (end == 0)
4242 {
4243 if (errmsg == NULL)
4244 {
4245#ifdef FEAT_MBYTE
4246 if (write_info.bw_conv_error)
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00004247 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004248 else
4249#endif
4250 if (got_int)
4251 errmsg = (char_u *)_(e_interr);
4252 else
4253 errmsg = (char_u *)_("E514: write error (file system full?)");
4254 }
4255
4256 /*
4257 * If we have a backup file, try to put it in place of the new file,
4258 * because the new file is probably corrupt. This avoids loosing the
4259 * original file when trying to make a backup when writing the file a
4260 * second time.
4261 * When "backup_copy" is set we need to copy the backup over the new
4262 * file. Otherwise rename the backup file.
4263 * If this is OK, don't give the extra warning message.
4264 */
4265 if (backup != NULL)
4266 {
4267 if (backup_copy)
4268 {
4269 /* This may take a while, if we were interrupted let the user
4270 * know we got the message. */
4271 if (got_int)
4272 {
4273 MSG(_(e_interr));
4274 out_flush();
4275 }
4276 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4277 {
4278 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004279 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4280 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004281 {
4282 /* copy the file. */
4283 write_info.bw_buf = smallbuf;
4284#ifdef HAS_BW_FLAGS
4285 write_info.bw_flags = FIO_NOCONVERT;
4286#endif
4287 while ((write_info.bw_len = vim_read(fd, smallbuf,
4288 SMBUFSIZE)) > 0)
4289 if (buf_write_bytes(&write_info) == FAIL)
4290 break;
4291
4292 if (close(write_info.bw_fd) >= 0
4293 && write_info.bw_len == 0)
4294 end = 1; /* success */
4295 }
4296 close(fd); /* ignore errors for closing read file */
4297 }
4298 }
4299 else
4300 {
4301 if (vim_rename(backup, fname) == 0)
4302 end = 1;
4303 }
4304 }
4305 goto fail;
4306 }
4307
4308 lnum -= start; /* compute number of written lines */
4309 --no_wait_return; /* may wait for return now */
4310
4311#if !(defined(UNIX) || defined(VMS))
4312 fname = sfname; /* use shortname now, for the messages */
4313#endif
4314 if (!filtering)
4315 {
4316 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4317 c = FALSE;
4318#ifdef FEAT_MBYTE
4319 if (write_info.bw_conv_error)
4320 {
4321 STRCAT(IObuff, _(" CONVERSION ERROR"));
4322 c = TRUE;
4323 }
4324 else if (notconverted)
4325 {
4326 STRCAT(IObuff, _("[NOT converted]"));
4327 c = TRUE;
4328 }
4329 else if (converted)
4330 {
4331 STRCAT(IObuff, _("[converted]"));
4332 c = TRUE;
4333 }
4334#endif
4335 if (device)
4336 {
4337 STRCAT(IObuff, _("[Device]"));
4338 c = TRUE;
4339 }
4340 else if (newfile)
4341 {
4342 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4343 c = TRUE;
4344 }
4345 if (no_eol)
4346 {
4347 msg_add_eol();
4348 c = TRUE;
4349 }
4350 /* may add [unix/dos/mac] */
4351 if (msg_add_fileformat(fileformat))
4352 c = TRUE;
4353#ifdef FEAT_CRYPT
4354 if (wb_flags & FIO_ENCRYPTED)
4355 {
4356 STRCAT(IObuff, _("[crypted]"));
4357 c = TRUE;
4358 }
4359#endif
4360 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4361 if (!shortmess(SHM_WRITE))
4362 {
4363 if (append)
4364 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4365 else
4366 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4367 }
4368
4369 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
4370 keep_msg_attr = 0;
4371 }
4372
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004373 /* When written everything correctly: reset 'modified'. Unless not
4374 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar292ad192005-12-11 21:29:51 +00004375 if (reset_changed && whole && !append
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376#ifdef FEAT_MBYTE
4377 && !write_info.bw_conv_error
4378#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004379 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4380 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381 {
4382 unchanged(buf, TRUE);
4383 u_unchanged(buf);
4384 }
4385
4386 /*
4387 * If written to the current file, update the timestamp of the swap file
4388 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4389 */
4390 if (overwriting)
4391 {
4392 ml_timestamp(buf);
Bram Moolenaar292ad192005-12-11 21:29:51 +00004393 if (append)
4394 buf->b_flags &= ~BF_NEW;
4395 else
4396 buf->b_flags &= ~BF_WRITE_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397 }
4398
4399 /*
4400 * If we kept a backup until now, and we are in patch mode, then we make
4401 * the backup file our 'original' file.
4402 */
4403 if (*p_pm && dobackup)
4404 {
4405 char *org = (char *)buf_modname(
4406#ifdef SHORT_FNAME
4407 TRUE,
4408#else
4409 (buf->b_p_sn || buf->b_shortname),
4410#endif
4411 fname, p_pm, FALSE);
4412
4413 if (backup != NULL)
4414 {
4415 struct stat st;
4416
4417 /*
4418 * If the original file does not exist yet
4419 * the current backup file becomes the original file
4420 */
4421 if (org == NULL)
4422 EMSG(_("E205: Patchmode: can't save original file"));
4423 else if (mch_stat(org, &st) < 0)
4424 {
4425 vim_rename(backup, (char_u *)org);
4426 vim_free(backup); /* don't delete the file */
4427 backup = NULL;
4428#ifdef UNIX
4429 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4430#endif
4431 }
4432 }
4433 /*
4434 * If there is no backup file, remember that a (new) file was
4435 * created.
4436 */
4437 else
4438 {
4439 int empty_fd;
4440
4441 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00004442 || (empty_fd = mch_open(org,
4443 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004444 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004445 EMSG(_("E206: patchmode: can't touch empty original file"));
4446 else
4447 close(empty_fd);
4448 }
4449 if (org != NULL)
4450 {
4451 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4452 vim_free(org);
4453 }
4454 }
4455
4456 /*
4457 * Remove the backup unless 'backup' option is set
4458 */
4459 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4460 EMSG(_("E207: Can't delete backup file"));
4461
4462#ifdef FEAT_SUN_WORKSHOP
4463 if (usingSunWorkShop)
4464 workshop_file_saved((char *) ffname);
4465#endif
4466
4467 goto nofail;
4468
4469 /*
4470 * Finish up. We get here either after failure or success.
4471 */
4472fail:
4473 --no_wait_return; /* may wait for return now */
4474nofail:
4475
4476 /* Done saving, we accept changed buffer warnings again */
4477 buf->b_saving = FALSE;
4478
4479 vim_free(backup);
4480 if (buffer != smallbuf)
4481 vim_free(buffer);
4482#ifdef FEAT_MBYTE
4483 vim_free(fenc_tofree);
4484 vim_free(write_info.bw_conv_buf);
4485# ifdef USE_ICONV
4486 if (write_info.bw_iconv_fd != (iconv_t)-1)
4487 {
4488 iconv_close(write_info.bw_iconv_fd);
4489 write_info.bw_iconv_fd = (iconv_t)-1;
4490 }
4491# endif
4492#endif
4493#ifdef HAVE_ACL
4494 mch_free_acl(acl);
4495#endif
4496
4497 if (errmsg != NULL)
4498 {
4499 int numlen = errnum != NULL ? STRLEN(errnum) : 0;
4500
4501 attr = hl_attr(HLF_E); /* set highlight for error messages */
4502 msg_add_fname(buf,
4503#ifndef UNIX
4504 sfname
4505#else
4506 fname
4507#endif
4508 ); /* put file name in IObuff with quotes */
4509 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4510 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4511 /* If the error message has the form "is ...", put the error number in
4512 * front of the file name. */
4513 if (errnum != NULL)
4514 {
4515 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4516 mch_memmove(IObuff, errnum, (size_t)numlen);
4517 }
4518 STRCAT(IObuff, errmsg);
4519 emsg(IObuff);
4520
4521 retval = FAIL;
4522 if (end == 0)
4523 {
4524 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4525 attr | MSG_HIST);
4526 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4527 attr | MSG_HIST);
4528
4529 /* Update the timestamp to avoid an "overwrite changed file"
4530 * prompt when writing again. */
4531 if (mch_stat((char *)fname, &st_old) >= 0)
4532 {
4533 buf_store_time(buf, &st_old, fname);
4534 buf->b_mtime_read = buf->b_mtime;
4535 }
4536 }
4537 }
4538 msg_scroll = msg_save;
4539
4540#ifdef FEAT_AUTOCMD
4541#ifdef FEAT_EVAL
4542 if (!should_abort(retval))
4543#else
4544 if (!got_int)
4545#endif
4546 {
4547 aco_save_T aco;
4548
4549 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4550
4551 /*
4552 * Apply POST autocommands.
4553 * Careful: The autocommands may call buf_write() recursively!
4554 */
4555 aucmd_prepbuf(&aco, buf);
4556
4557 if (append)
4558 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4559 FALSE, curbuf, eap);
4560 else if (filtering)
4561 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4562 FALSE, curbuf, eap);
4563 else if (reset_changed && whole)
4564 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4565 FALSE, curbuf, eap);
4566 else
4567 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4568 FALSE, curbuf, eap);
4569
4570 /* restore curwin/curbuf and a few other things */
4571 aucmd_restbuf(&aco);
4572
4573#ifdef FEAT_EVAL
4574 if (aborting()) /* autocmds may abort script processing */
4575 retval = FALSE;
4576#endif
4577 }
4578#endif
4579
4580 got_int |= prev_got_int;
4581
4582#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4583 /* Update machine specific information. */
4584 mch_post_buffer_write(buf);
4585#endif
4586 return retval;
4587}
4588
4589/*
Bram Moolenaar2d3f4892006-01-20 23:02:51 +00004590 * Set the name of the current buffer. Use when the buffer doesn't have a
4591 * name and a ":r" or ":w" command with a file name is used.
4592 */
4593 static int
4594set_rw_fname(fname, sfname)
4595 char_u *fname;
4596 char_u *sfname;
4597{
4598#ifdef FEAT_AUTOCMD
4599 /* It's like the unnamed buffer is deleted.... */
4600 if (curbuf->b_p_bl)
4601 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
4602 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
4603# ifdef FEAT_EVAL
4604 if (aborting()) /* autocmds may abort script processing */
4605 return FAIL;
4606# endif
4607#endif
4608
4609 if (setfname(curbuf, fname, sfname, FALSE) == OK)
4610 curbuf->b_flags |= BF_NOTEDITED;
4611
4612#ifdef FEAT_AUTOCMD
4613 /* ....and a new named one is created */
4614 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
4615 if (curbuf->b_p_bl)
4616 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
4617# ifdef FEAT_EVAL
4618 if (aborting()) /* autocmds may abort script processing */
4619 return FAIL;
4620# endif
4621
4622 /* Do filetype detection now if 'filetype' is empty. */
4623 if (*curbuf->b_p_ft == NUL)
4624 {
4625 (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE);
4626 do_modelines(FALSE);
4627 }
4628#endif
4629
4630 return OK;
4631}
4632
4633/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634 * Put file name into IObuff with quotes.
4635 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004636 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637msg_add_fname(buf, fname)
4638 buf_T *buf;
4639 char_u *fname;
4640{
4641 if (fname == NULL)
4642 fname = (char_u *)"-stdin-";
4643 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4644 IObuff[0] = '"';
4645 STRCAT(IObuff, "\" ");
4646}
4647
4648/*
4649 * Append message for text mode to IObuff.
4650 * Return TRUE if something appended.
4651 */
4652 static int
4653msg_add_fileformat(eol_type)
4654 int eol_type;
4655{
4656#ifndef USE_CRNL
4657 if (eol_type == EOL_DOS)
4658 {
4659 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4660 return TRUE;
4661 }
4662#endif
4663#ifndef USE_CR
4664 if (eol_type == EOL_MAC)
4665 {
4666 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4667 return TRUE;
4668 }
4669#endif
4670#if defined(USE_CRNL) || defined(USE_CR)
4671 if (eol_type == EOL_UNIX)
4672 {
4673 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4674 return TRUE;
4675 }
4676#endif
4677 return FALSE;
4678}
4679
4680/*
4681 * Append line and character count to IObuff.
4682 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004683 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004684msg_add_lines(insert_space, lnum, nchars)
4685 int insert_space;
4686 long lnum;
4687 long nchars;
4688{
4689 char_u *p;
4690
4691 p = IObuff + STRLEN(IObuff);
4692
4693 if (insert_space)
4694 *p++ = ' ';
4695 if (shortmess(SHM_LINES))
4696 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4697 else
4698 {
4699 if (lnum == 1)
4700 STRCPY(p, _("1 line, "));
4701 else
4702 sprintf((char *)p, _("%ld lines, "), lnum);
4703 p += STRLEN(p);
4704 if (nchars == 1)
4705 STRCPY(p, _("1 character"));
4706 else
4707 sprintf((char *)p, _("%ld characters"), nchars);
4708 }
4709}
4710
4711/*
4712 * Append message for missing line separator to IObuff.
4713 */
4714 static void
4715msg_add_eol()
4716{
4717 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4718}
4719
4720/*
4721 * Check modification time of file, before writing to it.
4722 * The size isn't checked, because using a tool like "gzip" takes care of
4723 * using the same timestamp but can't set the size.
4724 */
4725 static int
4726check_mtime(buf, st)
4727 buf_T *buf;
4728 struct stat *st;
4729{
4730 if (buf->b_mtime_read != 0
4731 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4732 {
4733 msg_scroll = TRUE; /* don't overwrite messages here */
4734 msg_silent = 0; /* must give this prompt */
4735 /* don't use emsg() here, don't want to flush the buffers */
4736 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4737 hl_attr(HLF_E));
4738 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4739 TRUE) == 'n')
4740 return FAIL;
4741 msg_scroll = FALSE; /* always overwrite the file message now */
4742 }
4743 return OK;
4744}
4745
4746 static int
4747time_differs(t1, t2)
4748 long t1, t2;
4749{
4750#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4751 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4752 * the seconds. Since the roundoff is done when flushing the inode, the
4753 * time may change unexpectedly by one second!!! */
4754 return (t1 - t2 > 1 || t2 - t1 > 1);
4755#else
4756 return (t1 != t2);
4757#endif
4758}
4759
4760/*
4761 * Call write() to write a number of bytes to the file.
4762 * Also handles encryption and 'encoding' conversion.
4763 *
4764 * Return FAIL for failure, OK otherwise.
4765 */
4766 static int
4767buf_write_bytes(ip)
4768 struct bw_info *ip;
4769{
4770 int wlen;
4771 char_u *buf = ip->bw_buf; /* data to write */
4772 int len = ip->bw_len; /* length of data */
4773#ifdef HAS_BW_FLAGS
4774 int flags = ip->bw_flags; /* extra flags */
4775#endif
4776
4777#ifdef FEAT_MBYTE
4778 /*
4779 * Skip conversion when writing the crypt magic number or the BOM.
4780 */
4781 if (!(flags & FIO_NOCONVERT))
4782 {
4783 char_u *p;
4784 unsigned c;
4785 int n;
4786
4787 if (flags & FIO_UTF8)
4788 {
4789 /*
4790 * Convert latin1 in the buffer to UTF-8 in the file.
4791 */
4792 p = ip->bw_conv_buf; /* translate to buffer */
4793 for (wlen = 0; wlen < len; ++wlen)
4794 p += utf_char2bytes(buf[wlen], p);
4795 buf = ip->bw_conv_buf;
4796 len = (int)(p - ip->bw_conv_buf);
4797 }
4798 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4799 {
4800 /*
4801 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4802 * Latin1 chars in the file.
4803 */
4804 if (flags & FIO_LATIN1)
4805 p = buf; /* translate in-place (can only get shorter) */
4806 else
4807 p = ip->bw_conv_buf; /* translate to buffer */
4808 for (wlen = 0; wlen < len; wlen += n)
4809 {
4810 if (wlen == 0 && ip->bw_restlen != 0)
4811 {
4812 int l;
4813
4814 /* Use remainder of previous call. Append the start of
4815 * buf[] to get a full sequence. Might still be too
4816 * short! */
4817 l = CONV_RESTLEN - ip->bw_restlen;
4818 if (l > len)
4819 l = len;
4820 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004821 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004822 if (n > ip->bw_restlen + len)
4823 {
4824 /* We have an incomplete byte sequence at the end to
4825 * be written. We can't convert it without the
4826 * remaining bytes. Keep them for the next call. */
4827 if (ip->bw_restlen + len > CONV_RESTLEN)
4828 return FAIL;
4829 ip->bw_restlen += len;
4830 break;
4831 }
4832 if (n > 1)
4833 c = utf_ptr2char(ip->bw_rest);
4834 else
4835 c = ip->bw_rest[0];
4836 if (n >= ip->bw_restlen)
4837 {
4838 n -= ip->bw_restlen;
4839 ip->bw_restlen = 0;
4840 }
4841 else
4842 {
4843 ip->bw_restlen -= n;
4844 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4845 (size_t)ip->bw_restlen);
4846 n = 0;
4847 }
4848 }
4849 else
4850 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004851 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 if (n > len - wlen)
4853 {
4854 /* We have an incomplete byte sequence at the end to
4855 * be written. We can't convert it without the
4856 * remaining bytes. Keep them for the next call. */
4857 if (len - wlen > CONV_RESTLEN)
4858 return FAIL;
4859 ip->bw_restlen = len - wlen;
4860 mch_memmove(ip->bw_rest, buf + wlen,
4861 (size_t)ip->bw_restlen);
4862 break;
4863 }
4864 if (n > 1)
4865 c = utf_ptr2char(buf + wlen);
4866 else
4867 c = buf[wlen];
4868 }
4869
4870 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4871 }
4872 if (flags & FIO_LATIN1)
4873 len = (int)(p - buf);
4874 else
4875 {
4876 buf = ip->bw_conv_buf;
4877 len = (int)(p - ip->bw_conv_buf);
4878 }
4879 }
4880
4881# ifdef WIN3264
4882 else if (flags & FIO_CODEPAGE)
4883 {
4884 /*
4885 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
4886 * codepage.
4887 */
4888 char_u *from;
4889 size_t fromlen;
4890 char_u *to;
4891 int u8c;
4892 BOOL bad = FALSE;
4893 int needed;
4894
4895 if (ip->bw_restlen > 0)
4896 {
4897 /* Need to concatenate the remainder of the previous call and
4898 * the bytes of the current call. Use the end of the
4899 * conversion buffer for this. */
4900 fromlen = len + ip->bw_restlen;
4901 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4902 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4903 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4904 }
4905 else
4906 {
4907 from = buf;
4908 fromlen = len;
4909 }
4910
4911 to = ip->bw_conv_buf;
4912 if (enc_utf8)
4913 {
4914 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
4915 * The buffer has been allocated to be big enough. */
4916 while (fromlen > 0)
4917 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004918 n = utf_ptr2len_len(from, fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004919 if (n > (int)fromlen) /* incomplete byte sequence */
4920 break;
4921 u8c = utf_ptr2char(from);
4922 *to++ = (u8c & 0xff);
4923 *to++ = (u8c >> 8);
4924 fromlen -= n;
4925 from += n;
4926 }
4927
4928 /* Copy remainder to ip->bw_rest[] to be used for the next
4929 * call. */
4930 if (fromlen > CONV_RESTLEN)
4931 {
4932 /* weird overlong sequence */
4933 ip->bw_conv_error = TRUE;
4934 return FAIL;
4935 }
4936 mch_memmove(ip->bw_rest, from, fromlen);
4937 ip->bw_restlen = fromlen;
4938 }
4939 else
4940 {
4941 /* Convert from enc_codepage to UCS-2, to the start of the
4942 * buffer. The buffer has been allocated to be big enough. */
4943 ip->bw_restlen = 0;
4944 needed = MultiByteToWideChar(enc_codepage,
4945 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
4946 NULL, 0);
4947 if (needed == 0)
4948 {
4949 /* When conversion fails there may be a trailing byte. */
4950 needed = MultiByteToWideChar(enc_codepage,
4951 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
4952 NULL, 0);
4953 if (needed == 0)
4954 {
4955 /* Conversion doesn't work. */
4956 ip->bw_conv_error = TRUE;
4957 return FAIL;
4958 }
4959 /* Save the trailing byte for the next call. */
4960 ip->bw_rest[0] = from[fromlen - 1];
4961 ip->bw_restlen = 1;
4962 }
4963 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
4964 (LPCSTR)from, fromlen - ip->bw_restlen,
4965 (LPWSTR)to, needed);
4966 if (needed == 0)
4967 {
4968 /* Safety check: Conversion doesn't work. */
4969 ip->bw_conv_error = TRUE;
4970 return FAIL;
4971 }
4972 to += needed * 2;
4973 }
4974
4975 fromlen = to - ip->bw_conv_buf;
4976 buf = to;
4977# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
4978 if (FIO_GET_CP(flags) == CP_UTF8)
4979 {
4980 /* Convert from UCS-2 to UTF-8, using the remainder of the
4981 * conversion buffer. Fails when out of space. */
4982 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
4983 {
4984 u8c = *from++;
4985 u8c += (*from++ << 8);
4986 to += utf_char2bytes(u8c, to);
4987 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
4988 {
4989 ip->bw_conv_error = TRUE;
4990 return FAIL;
4991 }
4992 }
4993 len = to - buf;
4994 }
4995 else
4996#endif
4997 {
4998 /* Convert from UCS-2 to the codepage, using the remainder of
4999 * the conversion buffer. If the conversion uses the default
5000 * character "0", the data doesn't fit in this encoding, so
5001 * fail. */
5002 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
5003 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
5004 (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
5005 if (bad)
5006 {
5007 ip->bw_conv_error = TRUE;
5008 return FAIL;
5009 }
5010 }
5011 }
5012# endif
5013
5014# ifdef MACOS_X
5015 else if (flags & FIO_MACROMAN)
5016 {
5017 /*
5018 * Convert UTF-8 or latin1 to Apple MacRoman.
5019 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020 char_u *from;
5021 size_t fromlen;
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
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005039 if (enc2macroman(from, fromlen,
5040 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
5041 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005042 {
5043 ip->bw_conv_error = TRUE;
5044 return FAIL;
5045 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047 }
5048# endif
5049
5050# ifdef USE_ICONV
5051 if (ip->bw_iconv_fd != (iconv_t)-1)
5052 {
5053 const char *from;
5054 size_t fromlen;
5055 char *to;
5056 size_t tolen;
5057
5058 /* Convert with iconv(). */
5059 if (ip->bw_restlen > 0)
5060 {
5061 /* Need to concatenate the remainder of the previous call and
5062 * the bytes of the current call. Use the end of the
5063 * conversion buffer for this. */
5064 fromlen = len + ip->bw_restlen;
5065 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
5066 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
5067 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
5068 tolen = ip->bw_conv_buflen - fromlen;
5069 }
5070 else
5071 {
5072 from = (const char *)buf;
5073 fromlen = len;
5074 tolen = ip->bw_conv_buflen;
5075 }
5076 to = (char *)ip->bw_conv_buf;
5077
5078 if (ip->bw_first)
5079 {
5080 size_t save_len = tolen;
5081
5082 /* output the initial shift state sequence */
5083 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
5084
5085 /* There is a bug in iconv() on Linux (which appears to be
5086 * wide-spread) which sets "to" to NULL and messes up "tolen".
5087 */
5088 if (to == NULL)
5089 {
5090 to = (char *)ip->bw_conv_buf;
5091 tolen = save_len;
5092 }
5093 ip->bw_first = FALSE;
5094 }
5095
5096 /*
5097 * If iconv() has an error or there is not enough room, fail.
5098 */
5099 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
5100 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
5101 || fromlen > CONV_RESTLEN)
5102 {
5103 ip->bw_conv_error = TRUE;
5104 return FAIL;
5105 }
5106
5107 /* copy remainder to ip->bw_rest[] to be used for the next call. */
5108 if (fromlen > 0)
5109 mch_memmove(ip->bw_rest, (void *)from, fromlen);
5110 ip->bw_restlen = (int)fromlen;
5111
5112 buf = ip->bw_conv_buf;
5113 len = (int)((char_u *)to - ip->bw_conv_buf);
5114 }
5115# endif
5116 }
5117#endif /* FEAT_MBYTE */
5118
5119#ifdef FEAT_CRYPT
5120 if (flags & FIO_ENCRYPTED) /* encrypt the data */
5121 {
5122 int ztemp, t, i;
5123
5124 for (i = 0; i < len; i++)
5125 {
5126 ztemp = buf[i];
5127 buf[i] = ZENCODE(ztemp, t);
5128 }
5129 }
5130#endif
5131
5132 /* Repeat the write(), it may be interrupted by a signal. */
5133 while (len)
5134 {
5135 wlen = vim_write(ip->bw_fd, buf, len);
5136 if (wlen <= 0) /* error! */
5137 return FAIL;
5138 len -= wlen;
5139 buf += wlen;
5140 }
5141 return OK;
5142}
5143
5144#ifdef FEAT_MBYTE
5145/*
5146 * Convert a Unicode character to bytes.
5147 */
5148 static int
5149ucs2bytes(c, pp, flags)
5150 unsigned c; /* in: character */
5151 char_u **pp; /* in/out: pointer to result */
5152 int flags; /* FIO_ flags */
5153{
5154 char_u *p = *pp;
5155 int error = FALSE;
5156 int cc;
5157
5158
5159 if (flags & FIO_UCS4)
5160 {
5161 if (flags & FIO_ENDIAN_L)
5162 {
5163 *p++ = c;
5164 *p++ = (c >> 8);
5165 *p++ = (c >> 16);
5166 *p++ = (c >> 24);
5167 }
5168 else
5169 {
5170 *p++ = (c >> 24);
5171 *p++ = (c >> 16);
5172 *p++ = (c >> 8);
5173 *p++ = c;
5174 }
5175 }
5176 else if (flags & (FIO_UCS2 | FIO_UTF16))
5177 {
5178 if (c >= 0x10000)
5179 {
5180 if (flags & FIO_UTF16)
5181 {
5182 /* Make two words, ten bits of the character in each. First
5183 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
5184 c -= 0x10000;
5185 if (c >= 0x100000)
5186 error = TRUE;
5187 cc = ((c >> 10) & 0x3ff) + 0xd800;
5188 if (flags & FIO_ENDIAN_L)
5189 {
5190 *p++ = cc;
5191 *p++ = ((unsigned)cc >> 8);
5192 }
5193 else
5194 {
5195 *p++ = ((unsigned)cc >> 8);
5196 *p++ = cc;
5197 }
5198 c = (c & 0x3ff) + 0xdc00;
5199 }
5200 else
5201 error = TRUE;
5202 }
5203 if (flags & FIO_ENDIAN_L)
5204 {
5205 *p++ = c;
5206 *p++ = (c >> 8);
5207 }
5208 else
5209 {
5210 *p++ = (c >> 8);
5211 *p++ = c;
5212 }
5213 }
5214 else /* Latin1 */
5215 {
5216 if (c >= 0x100)
5217 {
5218 error = TRUE;
5219 *p++ = 0xBF;
5220 }
5221 else
5222 *p++ = c;
5223 }
5224
5225 *pp = p;
5226 return error;
5227}
5228
5229/*
5230 * Return TRUE if "a" and "b" are the same 'encoding'.
5231 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5232 */
5233 static int
5234same_encoding(a, b)
5235 char_u *a;
5236 char_u *b;
5237{
5238 int f;
5239
5240 if (STRCMP(a, b) == 0)
5241 return TRUE;
5242 f = get_fio_flags(a);
5243 return (f != 0 && get_fio_flags(b) == f);
5244}
5245
5246/*
5247 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5248 * internal conversion.
5249 * if "ptr" is an empty string, use 'encoding'.
5250 */
5251 static int
5252get_fio_flags(ptr)
5253 char_u *ptr;
5254{
5255 int prop;
5256
5257 if (*ptr == NUL)
5258 ptr = p_enc;
5259
5260 prop = enc_canon_props(ptr);
5261 if (prop & ENC_UNICODE)
5262 {
5263 if (prop & ENC_2BYTE)
5264 {
5265 if (prop & ENC_ENDIAN_L)
5266 return FIO_UCS2 | FIO_ENDIAN_L;
5267 return FIO_UCS2;
5268 }
5269 if (prop & ENC_4BYTE)
5270 {
5271 if (prop & ENC_ENDIAN_L)
5272 return FIO_UCS4 | FIO_ENDIAN_L;
5273 return FIO_UCS4;
5274 }
5275 if (prop & ENC_2WORD)
5276 {
5277 if (prop & ENC_ENDIAN_L)
5278 return FIO_UTF16 | FIO_ENDIAN_L;
5279 return FIO_UTF16;
5280 }
5281 return FIO_UTF8;
5282 }
5283 if (prop & ENC_LATIN1)
5284 return FIO_LATIN1;
5285 /* must be ENC_DBCS, requires iconv() */
5286 return 0;
5287}
5288
5289#ifdef WIN3264
5290/*
5291 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5292 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5293 * Used for conversion between 'encoding' and 'fileencoding'.
5294 */
5295 static int
5296get_win_fio_flags(ptr)
5297 char_u *ptr;
5298{
5299 int cp;
5300
5301 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5302 if (!enc_utf8 && enc_codepage <= 0)
5303 return 0;
5304
5305 cp = encname2codepage(ptr);
5306 if (cp == 0)
5307 {
5308# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5309 if (STRCMP(ptr, "utf-8") == 0)
5310 cp = CP_UTF8;
5311 else
5312# endif
5313 return 0;
5314 }
5315 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5316}
5317#endif
5318
5319#ifdef MACOS_X
5320/*
5321 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5322 * needed for the internal conversion to/from utf-8 or latin1.
5323 */
5324 static int
5325get_mac_fio_flags(ptr)
5326 char_u *ptr;
5327{
5328 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5329 && (enc_canon_props(ptr) & ENC_MACROMAN))
5330 return FIO_MACROMAN;
5331 return 0;
5332}
5333#endif
5334
5335/*
5336 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5337 * "size" must be at least 2.
5338 * Return the name of the encoding and set "*lenp" to the length.
5339 * Returns NULL when no BOM found.
5340 */
5341 static char_u *
5342check_for_bom(p, size, lenp, flags)
5343 char_u *p;
5344 long size;
5345 int *lenp;
5346 int flags;
5347{
5348 char *name = NULL;
5349 int len = 2;
5350
5351 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5352 && (flags == FIO_ALL || flags == 0))
5353 {
5354 name = "utf-8"; /* EF BB BF */
5355 len = 3;
5356 }
5357 else if (p[0] == 0xff && p[1] == 0xfe)
5358 {
5359 if (size >= 4 && p[2] == 0 && p[3] == 0
5360 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5361 {
5362 name = "ucs-4le"; /* FF FE 00 00 */
5363 len = 4;
5364 }
5365 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5366 name = "ucs-2le"; /* FF FE */
5367 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5368 name = "utf-16le"; /* FF FE */
5369 }
5370 else if (p[0] == 0xfe && p[1] == 0xff
5371 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5372 {
5373 if (flags == FIO_UTF16)
5374 name = "utf-16"; /* FE FF */
5375 else
5376 name = "ucs-2"; /* FE FF */
5377 }
5378 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5379 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5380 {
5381 name = "ucs-4"; /* 00 00 FE FF */
5382 len = 4;
5383 }
5384
5385 *lenp = len;
5386 return (char_u *)name;
5387}
5388
5389/*
5390 * Generate a BOM in "buf[4]" for encoding "name".
5391 * Return the length of the BOM (zero when no BOM).
5392 */
5393 static int
5394make_bom(buf, name)
5395 char_u *buf;
5396 char_u *name;
5397{
5398 int flags;
5399 char_u *p;
5400
5401 flags = get_fio_flags(name);
5402
5403 /* Can't put a BOM in a non-Unicode file. */
5404 if (flags == FIO_LATIN1 || flags == 0)
5405 return 0;
5406
5407 if (flags == FIO_UTF8) /* UTF-8 */
5408 {
5409 buf[0] = 0xef;
5410 buf[1] = 0xbb;
5411 buf[2] = 0xbf;
5412 return 3;
5413 }
5414 p = buf;
5415 (void)ucs2bytes(0xfeff, &p, flags);
5416 return (int)(p - buf);
5417}
5418#endif
5419
5420/*
5421 * Try to find a shortname by comparing the fullname with the current
5422 * directory.
5423 * Returns NULL if not shorter name possible, pointer into "full_path"
5424 * otherwise.
5425 */
5426 char_u *
5427shorten_fname(full_path, dir_name)
5428 char_u *full_path;
5429 char_u *dir_name;
5430{
5431 int len;
5432 char_u *p;
5433
5434 if (full_path == NULL)
5435 return NULL;
5436 len = (int)STRLEN(dir_name);
5437 if (fnamencmp(dir_name, full_path, len) == 0)
5438 {
5439 p = full_path + len;
5440#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5441 /*
5442 * MSDOS: when a file is in the root directory, dir_name will end in a
5443 * slash, since C: by itself does not define a specific dir. In this
5444 * case p may already be correct. <negri>
5445 */
5446 if (!((len > 2) && (*(p - 2) == ':')))
5447#endif
5448 {
5449 if (vim_ispathsep(*p))
5450 ++p;
5451#ifndef VMS /* the path separator is always part of the path */
5452 else
5453 p = NULL;
5454#endif
5455 }
5456 }
5457#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5458 /*
5459 * When using a file in the current drive, remove the drive name:
5460 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5461 * a floppy from "A:\dir" to "B:\dir".
5462 */
5463 else if (len > 3
5464 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5465 && full_path[1] == ':'
5466 && vim_ispathsep(full_path[2]))
5467 p = full_path + 2;
5468#endif
5469 else
5470 p = NULL;
5471 return p;
5472}
5473
5474/*
5475 * Shorten filenames for all buffers.
5476 * When "force" is TRUE: Use full path from now on for files currently being
5477 * edited, both for file name and swap file name. Try to shorten the file
5478 * names a bit, if safe to do so.
5479 * When "force" is FALSE: Only try to shorten absolute file names.
5480 * For buffers that have buftype "nofile" or "scratch": never change the file
5481 * name.
5482 */
5483 void
5484shorten_fnames(force)
5485 int force;
5486{
5487 char_u dirname[MAXPATHL];
5488 buf_T *buf;
5489 char_u *p;
5490
5491 mch_dirname(dirname, MAXPATHL);
5492 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5493 {
5494 if (buf->b_fname != NULL
5495#ifdef FEAT_QUICKFIX
5496 && !bt_nofile(buf)
5497#endif
5498 && !path_with_url(buf->b_fname)
5499 && (force
5500 || buf->b_sfname == NULL
5501 || mch_isFullName(buf->b_sfname)))
5502 {
5503 vim_free(buf->b_sfname);
5504 buf->b_sfname = NULL;
5505 p = shorten_fname(buf->b_ffname, dirname);
5506 if (p != NULL)
5507 {
5508 buf->b_sfname = vim_strsave(p);
5509 buf->b_fname = buf->b_sfname;
5510 }
5511 if (p == NULL || buf->b_fname == NULL)
5512 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005513 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005514
5515 /* Always make the swap file name a full path, a "nofile" buffer may
5516 * also have a swap file. */
5517 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005518 }
5519#ifdef FEAT_WINDOWS
5520 status_redraw_all();
5521#endif
5522}
5523
5524#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5525 || defined(FEAT_GUI_MSWIN) \
5526 || defined(FEAT_GUI_MAC) \
5527 || defined(PROTO)
5528/*
5529 * Shorten all filenames in "fnames[count]" by current directory.
5530 */
5531 void
5532shorten_filenames(fnames, count)
5533 char_u **fnames;
5534 int count;
5535{
5536 int i;
5537 char_u dirname[MAXPATHL];
5538 char_u *p;
5539
5540 if (fnames == NULL || count < 1)
5541 return;
5542 mch_dirname(dirname, sizeof(dirname));
5543 for (i = 0; i < count; ++i)
5544 {
5545 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5546 {
5547 /* shorten_fname() returns pointer in given "fnames[i]". If free
5548 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5549 * "p" first then free fnames[i]. */
5550 p = vim_strsave(p);
5551 vim_free(fnames[i]);
5552 fnames[i] = p;
5553 }
5554 }
5555}
5556#endif
5557
5558/*
5559 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5560 * fo_o_h.ext for MSDOS or when shortname option set.
5561 *
5562 * Assumed that fname is a valid name found in the filesystem we assure that
5563 * the return value is a different name and ends in 'ext'.
5564 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5565 * characters otherwise.
5566 * Space for the returned name is allocated, must be freed later.
5567 * Returns NULL when out of memory.
5568 */
5569 char_u *
5570modname(fname, ext, prepend_dot)
5571 char_u *fname, *ext;
5572 int prepend_dot; /* may prepend a '.' to file name */
5573{
5574 return buf_modname(
5575#ifdef SHORT_FNAME
5576 TRUE,
5577#else
5578 (curbuf->b_p_sn || curbuf->b_shortname),
5579#endif
5580 fname, ext, prepend_dot);
5581}
5582
5583 char_u *
5584buf_modname(shortname, fname, ext, prepend_dot)
5585 int shortname; /* use 8.3 file name */
5586 char_u *fname, *ext;
5587 int prepend_dot; /* may prepend a '.' to file name */
5588{
5589 char_u *retval;
5590 char_u *s;
5591 char_u *e;
5592 char_u *ptr;
5593 int fnamelen, extlen;
5594
5595 extlen = (int)STRLEN(ext);
5596
5597 /*
5598 * If there is no file name we must get the name of the current directory
5599 * (we need the full path in case :cd is used).
5600 */
5601 if (fname == NULL || *fname == NUL)
5602 {
5603 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5604 if (retval == NULL)
5605 return NULL;
5606 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5607 (fnamelen = (int)STRLEN(retval)) == 0)
5608 {
5609 vim_free(retval);
5610 return NULL;
5611 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005612 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 {
5614 retval[fnamelen++] = PATHSEP;
5615 retval[fnamelen] = NUL;
5616 }
5617#ifndef SHORT_FNAME
5618 prepend_dot = FALSE; /* nothing to prepend a dot to */
5619#endif
5620 }
5621 else
5622 {
5623 fnamelen = (int)STRLEN(fname);
5624 retval = alloc((unsigned)(fnamelen + extlen + 3));
5625 if (retval == NULL)
5626 return NULL;
5627 STRCPY(retval, fname);
5628#ifdef VMS
5629 vms_remove_version(retval); /* we do not need versions here */
5630#endif
5631 }
5632
5633 /*
5634 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5635 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5636 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5637 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5638 */
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005639 for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005640 {
5641#ifndef RISCOS
5642 if (*ext == '.'
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005643# ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005644 && (!USE_LONG_FNAME || shortname)
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005645# else
5646# ifndef SHORT_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005647 && shortname
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005648# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005649# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005650 )
5651 if (*ptr == '.') /* replace '.' by '_' */
5652 *ptr = '_';
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005653#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005654 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005655 {
5656 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005657 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005658 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005659 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005660
5661 /* the file name has at most BASENAMELEN characters. */
5662#ifndef SHORT_FNAME
5663 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5664 ptr[BASENAMELEN] = '\0';
5665#endif
5666
5667 s = ptr + STRLEN(ptr);
5668
5669 /*
5670 * For 8.3 file names we may have to reduce the length.
5671 */
5672#ifdef USE_LONG_FNAME
5673 if (!USE_LONG_FNAME || shortname)
5674#else
5675# ifndef SHORT_FNAME
5676 if (shortname)
5677# endif
5678#endif
5679 {
5680 /*
5681 * If there is no file name, or the file name ends in '/', and the
5682 * extension starts with '.', put a '_' before the dot, because just
5683 * ".ext" is invalid.
5684 */
5685 if (fname == NULL || *fname == NUL
5686 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5687 {
5688#ifdef RISCOS
5689 if (*ext == '/')
5690#else
5691 if (*ext == '.')
5692#endif
5693 *s++ = '_';
5694 }
5695 /*
5696 * If the extension starts with '.', truncate the base name at 8
5697 * characters
5698 */
5699#ifdef RISCOS
5700 /* We normally use '/', but swap files are '_' */
5701 else if (*ext == '/' || *ext == '_')
5702#else
5703 else if (*ext == '.')
5704#endif
5705 {
5706 if (s - ptr > (size_t)8)
5707 {
5708 s = ptr + 8;
5709 *s = '\0';
5710 }
5711 }
5712 /*
5713 * If the extension doesn't start with '.', and the file name
5714 * doesn't have an extension yet, append a '.'
5715 */
5716#ifdef RISCOS
5717 else if ((e = vim_strchr(ptr, '/')) == NULL)
5718 *s++ = '/';
5719#else
5720 else if ((e = vim_strchr(ptr, '.')) == NULL)
5721 *s++ = '.';
5722#endif
5723 /*
5724 * If the extension doesn't start with '.', and there already is an
5725 * extension, it may need to be tructated
5726 */
5727 else if ((int)STRLEN(e) + extlen > 4)
5728 s = e + 4 - extlen;
5729 }
5730#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5731 /*
5732 * If there is no file name, and the extension starts with '.', put a
5733 * '_' before the dot, because just ".ext" may be invalid if it's on a
5734 * FAT partition, and on HPFS it doesn't matter.
5735 */
5736 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5737 *s++ = '_';
5738#endif
5739
5740 /*
5741 * Append the extention.
5742 * ext can start with '.' and cannot exceed 3 more characters.
5743 */
5744 STRCPY(s, ext);
5745
5746#ifndef SHORT_FNAME
5747 /*
5748 * Prepend the dot.
5749 */
5750 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5751#ifdef RISCOS
5752 '/'
5753#else
5754 '.'
5755#endif
5756#ifdef USE_LONG_FNAME
5757 && USE_LONG_FNAME
5758#endif
5759 )
5760 {
5761 mch_memmove(e + 1, e, STRLEN(e) + 1);
5762#ifdef RISCOS
5763 *e = '/';
5764#else
5765 *e = '.';
5766#endif
5767 }
5768#endif
5769
5770 /*
5771 * Check that, after appending the extension, the file name is really
5772 * different.
5773 */
5774 if (fname != NULL && STRCMP(fname, retval) == 0)
5775 {
5776 /* we search for a character that can be replaced by '_' */
5777 while (--s >= ptr)
5778 {
5779 if (*s != '_')
5780 {
5781 *s = '_';
5782 break;
5783 }
5784 }
5785 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5786 *ptr = 'v';
5787 }
5788 return retval;
5789}
5790
5791/*
5792 * Like fgets(), but if the file line is too long, it is truncated and the
5793 * rest of the line is thrown away. Returns TRUE for end-of-file.
5794 */
5795 int
5796vim_fgets(buf, size, fp)
5797 char_u *buf;
5798 int size;
5799 FILE *fp;
5800{
5801 char *eof;
5802#define FGETS_SIZE 200
5803 char tbuf[FGETS_SIZE];
5804
5805 buf[size - 2] = NUL;
5806#ifdef USE_CR
5807 eof = fgets_cr((char *)buf, size, fp);
5808#else
5809 eof = fgets((char *)buf, size, fp);
5810#endif
5811 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5812 {
5813 buf[size - 1] = NUL; /* Truncate the line */
5814
5815 /* Now throw away the rest of the line: */
5816 do
5817 {
5818 tbuf[FGETS_SIZE - 2] = NUL;
5819#ifdef USE_CR
5820 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5821#else
5822 fgets((char *)tbuf, FGETS_SIZE, fp);
5823#endif
5824 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5825 }
5826 return (eof == NULL);
5827}
5828
5829#if defined(USE_CR) || defined(PROTO)
5830/*
5831 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5832 * Returns TRUE for end-of-file.
5833 * Only used for the Mac, because it's much slower than vim_fgets().
5834 */
5835 int
5836tag_fgets(buf, size, fp)
5837 char_u *buf;
5838 int size;
5839 FILE *fp;
5840{
5841 int i = 0;
5842 int c;
5843 int eof = FALSE;
5844
5845 for (;;)
5846 {
5847 c = fgetc(fp);
5848 if (c == EOF)
5849 {
5850 eof = TRUE;
5851 break;
5852 }
5853 if (c == '\r')
5854 {
5855 /* Always store a NL for end-of-line. */
5856 if (i < size - 1)
5857 buf[i++] = '\n';
5858 c = fgetc(fp);
5859 if (c != '\n') /* Macintosh format: single CR. */
5860 ungetc(c, fp);
5861 break;
5862 }
5863 if (i < size - 1)
5864 buf[i++] = c;
5865 if (c == '\n')
5866 break;
5867 }
5868 buf[i] = NUL;
5869 return eof;
5870}
5871#endif
5872
5873/*
5874 * rename() only works if both files are on the same file system, this
5875 * function will (attempts to?) copy the file across if rename fails -- webb
5876 * Return -1 for failure, 0 for success.
5877 */
5878 int
5879vim_rename(from, to)
5880 char_u *from;
5881 char_u *to;
5882{
5883 int fd_in;
5884 int fd_out;
5885 int n;
5886 char *errmsg = NULL;
5887 char *buffer;
5888#ifdef AMIGA
5889 BPTR flock;
5890#endif
5891 struct stat st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005892 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005893#ifdef HAVE_ACL
5894 vim_acl_T acl; /* ACL from original file */
5895#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005896
5897 /*
5898 * When the names are identical, there is nothing to do.
5899 */
5900 if (fnamecmp(from, to) == 0)
5901 return 0;
5902
5903 /*
5904 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
5905 */
5906 if (mch_stat((char *)from, &st) < 0)
5907 return -1;
5908
5909 /*
5910 * Delete the "to" file, this is required on some systems to make the
5911 * mch_rename() work, on other systems it makes sure that we don't have
5912 * two files when the mch_rename() fails.
5913 */
5914
5915#ifdef AMIGA
5916 /*
5917 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
5918 * that the name of the "to" file is the same as the "from" file, even
5919 * though the names are different. To avoid the chance of accidently
5920 * deleting the "from" file (horror!) we lock it during the remove.
5921 *
5922 * When used for making a backup before writing the file: This should not
5923 * happen with ":w", because startscript() should detect this problem and
5924 * set buf->b_shortname, causing modname() to return a correct ".bak" file
5925 * name. This problem does exist with ":w filename", but then the
5926 * original file will be somewhere else so the backup isn't really
5927 * important. If autoscripting is off the rename may fail.
5928 */
5929 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
5930#endif
5931 mch_remove(to);
5932#ifdef AMIGA
5933 if (flock)
5934 UnLock(flock);
5935#endif
5936
5937 /*
5938 * First try a normal rename, return if it works.
5939 */
5940 if (mch_rename((char *)from, (char *)to) == 0)
5941 return 0;
5942
5943 /*
5944 * Rename() failed, try copying the file.
5945 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005946 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005947#ifdef HAVE_ACL
5948 /* For systems that support ACL: get the ACL from the original file. */
5949 acl = mch_get_acl(from);
5950#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005951 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
5952 if (fd_in == -1)
5953 return -1;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005954
5955 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00005956 fd_out = mch_open((char *)to,
5957 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005958 if (fd_out == -1)
5959 {
5960 close(fd_in);
5961 return -1;
5962 }
5963
5964 buffer = (char *)alloc(BUFSIZE);
5965 if (buffer == NULL)
5966 {
5967 close(fd_in);
5968 close(fd_out);
5969 return -1;
5970 }
5971
5972 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
5973 if (vim_write(fd_out, buffer, n) != n)
5974 {
5975 errmsg = _("E208: Error writing to \"%s\"");
5976 break;
5977 }
5978
5979 vim_free(buffer);
5980 close(fd_in);
5981 if (close(fd_out) < 0)
5982 errmsg = _("E209: Error closing \"%s\"");
5983 if (n < 0)
5984 {
5985 errmsg = _("E210: Error reading \"%s\"");
5986 to = from;
5987 }
Bram Moolenaarc6039d82005-12-02 00:44:04 +00005988#ifndef UNIX /* for Unix mch_open() already set ther permission */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005989 mch_setperm(to, perm);
Bram Moolenaarc6039d82005-12-02 00:44:04 +00005990#endif
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005991#ifdef HAVE_ACL
5992 mch_set_acl(to, acl);
5993#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005994 if (errmsg != NULL)
5995 {
5996 EMSG2(errmsg, to);
5997 return -1;
5998 }
5999 mch_remove(from);
6000 return 0;
6001}
6002
6003static int already_warned = FALSE;
6004
6005/*
6006 * Check if any not hidden buffer has been changed.
6007 * Postpone the check if there are characters in the stuff buffer, a global
6008 * command is being executed, a mapping is being executed or an autocommand is
6009 * busy.
6010 * Returns TRUE if some message was written (screen should be redrawn and
6011 * cursor positioned).
6012 */
6013 int
6014check_timestamps(focus)
6015 int focus; /* called for GUI focus event */
6016{
6017 buf_T *buf;
6018 int didit = 0;
6019 int n;
6020
6021 /* Don't check timestamps while system() or another low-level function may
6022 * cause us to lose and gain focus. */
6023 if (no_check_timestamps > 0)
6024 return FALSE;
6025
6026 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
6027 * event and we would keep on checking if the file is steadily growing.
6028 * Do check again after typing something. */
6029 if (focus && did_check_timestamps)
6030 {
6031 need_check_timestamps = TRUE;
6032 return FALSE;
6033 }
6034
6035 if (!stuff_empty() || global_busy || !typebuf_typed()
6036#ifdef FEAT_AUTOCMD
6037 || autocmd_busy
6038#endif
6039 )
6040 need_check_timestamps = TRUE; /* check later */
6041 else
6042 {
6043 ++no_wait_return;
6044 did_check_timestamps = TRUE;
6045 already_warned = FALSE;
6046 for (buf = firstbuf; buf != NULL; )
6047 {
6048 /* Only check buffers in a window. */
6049 if (buf->b_nwindows > 0)
6050 {
6051 n = buf_check_timestamp(buf, focus);
6052 if (didit < n)
6053 didit = n;
6054 if (n > 0 && !buf_valid(buf))
6055 {
6056 /* Autocommands have removed the buffer, start at the
6057 * first one again. */
6058 buf = firstbuf;
6059 continue;
6060 }
6061 }
6062 buf = buf->b_next;
6063 }
6064 --no_wait_return;
6065 need_check_timestamps = FALSE;
6066 if (need_wait_return && didit == 2)
6067 {
6068 /* make sure msg isn't overwritten */
6069 msg_puts((char_u *)"\n");
6070 out_flush();
6071 }
6072 }
6073 return didit;
6074}
6075
6076/*
6077 * Move all the lines from buffer "frombuf" to buffer "tobuf".
6078 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
6079 * empty.
6080 */
6081 static int
6082move_lines(frombuf, tobuf)
6083 buf_T *frombuf;
6084 buf_T *tobuf;
6085{
6086 buf_T *tbuf = curbuf;
6087 int retval = OK;
6088 linenr_T lnum;
6089 char_u *p;
6090
6091 /* Copy the lines in "frombuf" to "tobuf". */
6092 curbuf = tobuf;
6093 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
6094 {
6095 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
6096 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
6097 {
6098 vim_free(p);
6099 retval = FAIL;
6100 break;
6101 }
6102 vim_free(p);
6103 }
6104
6105 /* Delete all the lines in "frombuf". */
6106 if (retval != FAIL)
6107 {
6108 curbuf = frombuf;
6109 while (!bufempty())
6110 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
6111 {
6112 /* Oops! We could try putting back the saved lines, but that
6113 * might fail again... */
6114 retval = FAIL;
6115 break;
6116 }
6117 }
6118
6119 curbuf = tbuf;
6120 return retval;
6121}
6122
6123/*
6124 * Check if buffer "buf" has been changed.
6125 * Also check if the file for a new buffer unexpectedly appeared.
6126 * return 1 if a changed buffer was found.
6127 * return 2 if a message has been displayed.
6128 * return 0 otherwise.
6129 */
6130/*ARGSUSED*/
6131 int
6132buf_check_timestamp(buf, focus)
6133 buf_T *buf;
6134 int focus; /* called for GUI focus event */
6135{
6136 struct stat st;
6137 int stat_res;
6138 int retval = 0;
6139 char_u *path;
6140 char_u *tbuf;
6141 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00006142 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006143 int helpmesg = FALSE;
6144 int reload = FALSE;
6145#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6146 int can_reload = FALSE;
6147#endif
6148 size_t orig_size = buf->b_orig_size;
6149 int orig_mode = buf->b_orig_mode;
6150#ifdef FEAT_GUI
6151 int save_mouse_correct = need_mouse_correct;
6152#endif
6153#ifdef FEAT_AUTOCMD
6154 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006155 int n;
6156 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006157#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006158 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006159
6160 /* If there is no file name, the buffer is not loaded, 'buftype' is
6161 * set, we are in the middle of a save or being called recursively: ignore
6162 * this buffer. */
6163 if (buf->b_ffname == NULL
6164 || buf->b_ml.ml_mfp == NULL
6165#if defined(FEAT_QUICKFIX)
6166 || *buf->b_p_bt != NUL
6167#endif
6168 || buf->b_saving
6169#ifdef FEAT_AUTOCMD
6170 || busy
6171#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00006172#ifdef FEAT_NETBEANS_INTG
6173 || isNetbeansBuffer(buf)
6174#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006175 )
6176 return 0;
6177
6178 if ( !(buf->b_flags & BF_NOTEDITED)
6179 && buf->b_mtime != 0
6180 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
6181 || time_differs((long)st.st_mtime, buf->b_mtime)
6182#ifdef HAVE_ST_MODE
6183 || (int)st.st_mode != buf->b_orig_mode
6184#else
6185 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
6186#endif
6187 ))
6188 {
6189 retval = 1;
6190
Bram Moolenaar316059c2006-01-14 21:18:42 +00006191 /* set b_mtime to stop further warnings (e.g., when executing
6192 * FileChangedShell autocmd) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006193 if (stat_res < 0)
6194 {
6195 buf->b_mtime = 0;
6196 buf->b_orig_size = 0;
6197 buf->b_orig_mode = 0;
6198 }
6199 else
6200 buf_store_time(buf, &st, buf->b_ffname);
6201
6202 /* Don't do anything for a directory. Might contain the file
6203 * explorer. */
6204 if (mch_isdir(buf->b_fname))
6205 ;
6206
6207 /*
6208 * If 'autoread' is set, the buffer has no changes and the file still
6209 * exists, reload the buffer. Use the buffer-local option value if it
6210 * was set, the global option value otherwise.
6211 */
6212 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6213 && !bufIsChanged(buf) && stat_res >= 0)
6214 reload = TRUE;
6215 else
6216 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006217 if (stat_res < 0)
6218 reason = "deleted";
6219 else if (bufIsChanged(buf))
6220 reason = "conflict";
6221 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6222 reason = "changed";
6223 else if (orig_mode != buf->b_orig_mode)
6224 reason = "mode";
6225 else
6226 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006227
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006228#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006229 /*
6230 * Only give the warning if there are no FileChangedShell
6231 * autocommands.
6232 * Avoid being called recursively by setting "busy".
6233 */
6234 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006235# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006236 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6237 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006238# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006239 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6240 buf->b_fname, buf->b_fname, FALSE, buf);
6241 busy = FALSE;
6242 if (n)
6243 {
6244 if (!buf_valid(buf))
6245 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006246# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006247 s = get_vim_var_str(VV_FCS_CHOICE);
6248 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6249 reload = TRUE;
6250 else if (STRCMP(s, "ask") == 0)
6251 n = FALSE;
6252 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006253# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006254 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006255 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006256 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006257#endif
6258 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006259 if (*reason == 'd')
6260 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006261 else
6262 {
6263 helpmesg = TRUE;
6264#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6265 can_reload = TRUE;
6266#endif
6267 /*
6268 * Check if the file contents really changed to avoid
6269 * giving a warning when only the timestamp was set (e.g.,
6270 * checked out of CVS). Always warn when the buffer was
6271 * changed.
6272 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006273 if (reason[2] == 'n')
6274 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006275 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006276 mesg2 = _("See \":help W12\" for more info.");
6277 }
6278 else if (reason[1] == 'h')
6279 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006280 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006281 mesg2 = _("See \":help W11\" for more info.");
6282 }
6283 else if (*reason == 'm')
6284 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006285 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006286 mesg2 = _("See \":help W16\" for more info.");
6287 }
6288 /* Else: only timestamp changed, ignored */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006289 }
6290 }
6291 }
6292
6293 }
6294 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6295 && vim_fexists(buf->b_ffname))
6296 {
6297 retval = 1;
6298 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6299 buf->b_flags |= BF_NEW_W;
6300#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6301 can_reload = TRUE;
6302#endif
6303 }
6304
6305 if (mesg != NULL)
6306 {
6307 path = home_replace_save(buf, buf->b_fname);
6308 if (path != NULL)
6309 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006310 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006311 mesg2 = "";
6312 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6313 + STRLEN(mesg2) + 2));
6314 sprintf((char *)tbuf, mesg, path);
6315#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6316 if (can_reload)
6317 {
6318 if (*mesg2 != NUL)
6319 {
6320 STRCAT(tbuf, "\n");
6321 STRCAT(tbuf, mesg2);
6322 }
6323 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6324 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6325 reload = TRUE;
6326 }
6327 else
6328#endif
6329 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6330 {
6331 if (*mesg2 != NUL)
6332 {
6333 STRCAT(tbuf, "; ");
6334 STRCAT(tbuf, mesg2);
6335 }
6336 EMSG(tbuf);
6337 retval = 2;
6338 }
6339 else
6340 {
Bram Moolenaared203462004-06-16 11:19:22 +00006341# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006342 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006343# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006344 {
6345 msg_start();
6346 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6347 if (*mesg2 != NUL)
6348 msg_puts_attr((char_u *)mesg2,
6349 hl_attr(HLF_W) + MSG_HIST);
6350 msg_clr_eos();
6351 (void)msg_end();
6352 if (emsg_silent == 0)
6353 {
6354 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006355# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006356 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006357# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006358 /* give the user some time to think about it */
6359 ui_delay(1000L, TRUE);
6360
6361 /* don't redraw and erase the message */
6362 redraw_cmdline = FALSE;
6363 }
6364 }
6365 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006366 }
6367
6368 vim_free(path);
6369 vim_free(tbuf);
6370 }
6371 }
6372
6373 if (reload)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006374 /* Reload the buffer. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00006375 buf_reload(buf, orig_mode);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006376
6377#ifdef FEAT_GUI
6378 /* restore this in case an autocommand has set it; it would break
6379 * 'mousefocus' */
6380 need_mouse_correct = save_mouse_correct;
6381#endif
6382
6383 return retval;
6384}
6385
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006386/*
6387 * Reload a buffer that is already loaded.
6388 * Used when the file was changed outside of Vim.
Bram Moolenaar316059c2006-01-14 21:18:42 +00006389 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
6390 * buf->b_orig_mode may have been reset already.
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006391 */
6392 void
Bram Moolenaar316059c2006-01-14 21:18:42 +00006393buf_reload(buf, orig_mode)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006394 buf_T *buf;
Bram Moolenaar316059c2006-01-14 21:18:42 +00006395 int orig_mode;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006396{
6397 exarg_T ea;
6398 pos_T old_cursor;
6399 linenr_T old_topline;
6400 int old_ro = buf->b_p_ro;
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006401 buf_T *savebuf;
6402 int saved = OK;
6403#ifdef FEAT_AUTOCMD
6404 aco_save_T aco;
6405
6406 /* set curwin/curbuf for "buf" and save some things */
6407 aucmd_prepbuf(&aco, buf);
6408#else
6409 buf_T *save_curbuf = curbuf;
6410
6411 curbuf = buf;
6412 curwin->w_buffer = buf;
6413#endif
6414
6415 /* We only want to read the text from the file, not reset the syntax
6416 * highlighting, clear marks, diff status, etc. Force the fileformat
6417 * and encoding to be the same. */
6418 if (prep_exarg(&ea, buf) == OK)
6419 {
6420 old_cursor = curwin->w_cursor;
6421 old_topline = curwin->w_topline;
6422
6423 /*
6424 * To behave like when a new file is edited (matters for
6425 * BufReadPost autocommands) we first need to delete the current
6426 * buffer contents. But if reading the file fails we should keep
6427 * the old contents. Can't use memory only, the file might be
6428 * too big. Use a hidden buffer to move the buffer contents to.
6429 */
6430 if (bufempty())
6431 savebuf = NULL;
6432 else
6433 {
6434 /* Allocate a buffer without putting it in the buffer list. */
6435 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
6436 if (savebuf != NULL)
6437 {
6438 /* Open the memline. */
6439 curbuf = savebuf;
6440 curwin->w_buffer = savebuf;
Bram Moolenaar4770d092006-01-12 23:22:24 +00006441 saved = ml_open(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006442 curbuf = buf;
6443 curwin->w_buffer = buf;
6444 }
6445 if (savebuf == NULL || saved == FAIL
6446 || move_lines(buf, savebuf) == FAIL)
6447 {
6448 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6449 buf->b_fname);
6450 saved = FAIL;
6451 }
6452 }
6453
6454 if (saved == OK)
6455 {
6456 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6457#ifdef FEAT_AUTOCMD
6458 keep_filetype = TRUE; /* don't detect 'filetype' */
6459#endif
6460 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6461 (linenr_T)0,
6462 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6463 {
6464#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6465 if (!aborting())
6466#endif
6467 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
6468 if (savebuf != NULL)
6469 {
6470 /* Put the text back from the save buffer. First
6471 * delete any lines that readfile() added. */
6472 while (!bufempty())
6473 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
6474 == FAIL)
6475 break;
6476 (void)move_lines(savebuf, buf);
6477 }
6478 }
6479 else
6480 {
6481 /* Mark the buffer as unmodified and free undo info. */
6482 unchanged(buf, TRUE);
6483 u_blockfree(buf);
6484 u_clearall(buf);
6485 }
6486 }
6487 vim_free(ea.cmd);
6488
6489 if (savebuf != NULL)
6490 wipe_buffer(savebuf, FALSE);
6491
6492#ifdef FEAT_DIFF
6493 /* Invalidate diff info if necessary. */
6494 diff_invalidate();
6495#endif
6496
6497 /* Restore the topline and cursor position and check it (lines may
6498 * have been removed). */
6499 if (old_topline > curbuf->b_ml.ml_line_count)
6500 curwin->w_topline = curbuf->b_ml.ml_line_count;
6501 else
6502 curwin->w_topline = old_topline;
6503 curwin->w_cursor = old_cursor;
6504 check_cursor();
6505 update_topline();
6506#ifdef FEAT_AUTOCMD
6507 keep_filetype = FALSE;
6508#endif
6509#ifdef FEAT_FOLDING
6510 {
6511 win_T *wp;
6512
6513 /* Update folds unless they are defined manually. */
6514 FOR_ALL_WINDOWS(wp)
6515 if (wp->w_buffer == curwin->w_buffer
6516 && !foldmethodIsManual(wp))
6517 foldUpdateAll(wp);
6518 }
6519#endif
6520 /* If the mode didn't change and 'readonly' was set, keep the old
6521 * value; the user probably used the ":view" command. But don't
6522 * reset it, might have had a read error. */
6523 if (orig_mode == curbuf->b_orig_mode)
6524 curbuf->b_p_ro |= old_ro;
6525 }
6526
6527#ifdef FEAT_AUTOCMD
6528 /* restore curwin/curbuf and a few other things */
6529 aucmd_restbuf(&aco);
6530 /* Careful: autocommands may have made "buf" invalid! */
6531#else
6532 curwin->w_buffer = save_curbuf;
6533 curbuf = save_curbuf;
6534#endif
6535}
6536
Bram Moolenaar071d4272004-06-13 20:20:40 +00006537/*ARGSUSED*/
6538 void
6539buf_store_time(buf, st, fname)
6540 buf_T *buf;
6541 struct stat *st;
6542 char_u *fname;
6543{
6544 buf->b_mtime = (long)st->st_mtime;
6545 buf->b_orig_size = (size_t)st->st_size;
6546#ifdef HAVE_ST_MODE
6547 buf->b_orig_mode = (int)st->st_mode;
6548#else
6549 buf->b_orig_mode = mch_getperm(fname);
6550#endif
6551}
6552
6553/*
6554 * Adjust the line with missing eol, used for the next write.
6555 * Used for do_filter(), when the input lines for the filter are deleted.
6556 */
6557 void
6558write_lnum_adjust(offset)
6559 linenr_T offset;
6560{
Bram Moolenaardf177f62005-02-22 08:39:57 +00006561 if (write_no_eol_lnum != 0) /* only if there is a missing eol */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006562 write_no_eol_lnum += offset;
6563}
6564
6565#if defined(TEMPDIRNAMES) || defined(PROTO)
6566static long temp_count = 0; /* Temp filename counter. */
6567
6568/*
6569 * Delete the temp directory and all files it contains.
6570 */
6571 void
6572vim_deltempdir()
6573{
6574 char_u **files;
6575 int file_count;
6576 int i;
6577
6578 if (vim_tempdir != NULL)
6579 {
6580 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6581 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6582 EW_DIR|EW_FILE|EW_SILENT) == OK)
6583 {
6584 for (i = 0; i < file_count; ++i)
6585 mch_remove(files[i]);
6586 FreeWild(file_count, files);
6587 }
6588 gettail(NameBuff)[-1] = NUL;
6589 (void)mch_rmdir(NameBuff);
6590
6591 vim_free(vim_tempdir);
6592 vim_tempdir = NULL;
6593 }
6594}
6595#endif
6596
6597/*
6598 * vim_tempname(): Return a unique name that can be used for a temp file.
6599 *
6600 * The temp file is NOT created.
6601 *
6602 * The returned pointer is to allocated memory.
6603 * The returned pointer is NULL if no valid name was found.
6604 */
6605/*ARGSUSED*/
6606 char_u *
6607vim_tempname(extra_char)
6608 int extra_char; /* character to use in the name instead of '?' */
6609{
6610#ifdef USE_TMPNAM
6611 char_u itmp[L_tmpnam]; /* use tmpnam() */
6612#else
6613 char_u itmp[TEMPNAMELEN];
6614#endif
6615
6616#ifdef TEMPDIRNAMES
6617 static char *(tempdirs[]) = {TEMPDIRNAMES};
6618 int i;
6619 long nr;
6620 long off;
6621# ifndef EEXIST
6622 struct stat st;
6623# endif
6624
6625 /*
6626 * This will create a directory for private use by this instance of Vim.
6627 * This is done once, and the same directory is used for all temp files.
6628 * This method avoids security problems because of symlink attacks et al.
6629 * It's also a bit faster, because we only need to check for an existing
6630 * file when creating the directory and not for each temp file.
6631 */
6632 if (vim_tempdir == NULL)
6633 {
6634 /*
6635 * Try the entries in TEMPDIRNAMES to create the temp directory.
6636 */
6637 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6638 {
6639 /* expand $TMP, leave room for "/v1100000/999999999" */
6640 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6641 if (mch_isdir(itmp)) /* directory exists */
6642 {
6643# ifdef __EMX__
6644 /* If $TMP contains a forward slash (perhaps using bash or
6645 * tcsh), don't add a backslash, use a forward slash!
6646 * Adding 2 backslashes didn't work. */
6647 if (vim_strchr(itmp, '/') != NULL)
6648 STRCAT(itmp, "/");
6649 else
6650# endif
6651 add_pathsep(itmp);
6652
6653 /* Get an arbitrary number of up to 6 digits. When it's
6654 * unlikely that it already exists it will be faster,
6655 * otherwise it doesn't matter. The use of mkdir() avoids any
6656 * security problems because of the predictable number. */
6657 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6658
6659 /* Try up to 10000 different values until we find a name that
6660 * doesn't exist. */
6661 for (off = 0; off < 10000L; ++off)
6662 {
6663 int r;
6664#if defined(UNIX) || defined(VMS)
6665 mode_t umask_save;
6666#endif
6667
6668 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6669# ifndef EEXIST
6670 /* If mkdir() does not set errno to EEXIST, check for
6671 * existing file here. There is a race condition then,
6672 * although it's fail-safe. */
6673 if (mch_stat((char *)itmp, &st) >= 0)
6674 continue;
6675# endif
6676#if defined(UNIX) || defined(VMS)
6677 /* Make sure the umask doesn't remove the executable bit.
6678 * "repl" has been reported to use "177". */
6679 umask_save = umask(077);
6680#endif
6681 r = vim_mkdir(itmp, 0700);
6682#if defined(UNIX) || defined(VMS)
6683 (void)umask(umask_save);
6684#endif
6685 if (r == 0)
6686 {
6687 char_u *buf;
6688
6689 /* Directory was created, use this name.
6690 * Expand to full path; When using the current
6691 * directory a ":cd" would confuse us. */
6692 buf = alloc((unsigned)MAXPATHL + 1);
6693 if (buf != NULL)
6694 {
6695 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6696 == FAIL)
6697 STRCPY(buf, itmp);
6698# ifdef __EMX__
6699 if (vim_strchr(buf, '/') != NULL)
6700 STRCAT(buf, "/");
6701 else
6702# endif
6703 add_pathsep(buf);
6704 vim_tempdir = vim_strsave(buf);
6705 vim_free(buf);
6706 }
6707 break;
6708 }
6709# ifdef EEXIST
6710 /* If the mkdir() didn't fail because the file/dir exists,
6711 * we probably can't create any dir here, try another
6712 * place. */
6713 if (errno != EEXIST)
6714# endif
6715 break;
6716 }
6717 if (vim_tempdir != NULL)
6718 break;
6719 }
6720 }
6721 }
6722
6723 if (vim_tempdir != NULL)
6724 {
6725 /* There is no need to check if the file exists, because we own the
6726 * directory and nobody else creates a file in it. */
6727 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6728 return vim_strsave(itmp);
6729 }
6730
6731 return NULL;
6732
6733#else /* TEMPDIRNAMES */
6734
6735# ifdef WIN3264
6736 char szTempFile[_MAX_PATH + 1];
6737 char buf4[4];
6738 char_u *retval;
6739 char_u *p;
6740
6741 STRCPY(itmp, "");
6742 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6743 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6744 strcpy(buf4, "VIM");
6745 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6746 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6747 return NULL;
6748 /* GetTempFileName() will create the file, we don't want that */
6749 (void)DeleteFile(itmp);
6750
6751 /* Backslashes in a temp file name cause problems when filtering with
6752 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6753 * didn't set 'shellslash'. */
6754 retval = vim_strsave(itmp);
6755 if (*p_shcf == '-' || p_ssl)
6756 for (p = retval; *p; ++p)
6757 if (*p == '\\')
6758 *p = '/';
6759 return retval;
6760
6761# else /* WIN3264 */
6762
6763# ifdef USE_TMPNAM
6764 /* tmpnam() will make its own name */
6765 if (*tmpnam((char *)itmp) == NUL)
6766 return NULL;
6767# else
6768 char_u *p;
6769
6770# ifdef VMS_TEMPNAM
6771 /* mktemp() is not working on VMS. It seems to be
6772 * a do-nothing function. Therefore we use tempnam().
6773 */
6774 sprintf((char *)itmp, "VIM%c", extra_char);
6775 p = (char_u *)tempnam("tmp:", (char *)itmp);
6776 if (p != NULL)
6777 {
6778 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6779 * and VIM will then be unable to find the file later */
6780 STRCPY(itmp, p);
6781 STRCAT(itmp, ".txt");
6782 free(p);
6783 }
6784 else
6785 return NULL;
6786# else
6787 STRCPY(itmp, TEMPNAME);
6788 if ((p = vim_strchr(itmp, '?')) != NULL)
6789 *p = extra_char;
6790 if (mktemp((char *)itmp) == NULL)
6791 return NULL;
6792# endif
6793# endif
6794
6795 return vim_strsave(itmp);
6796# endif /* WIN3264 */
6797#endif /* TEMPDIRNAMES */
6798}
6799
6800#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6801/*
6802 * Convert all backslashes in fname to forward slashes in-place.
6803 */
6804 void
6805forward_slash(fname)
6806 char_u *fname;
6807{
6808 char_u *p;
6809
6810 for (p = fname; *p != NUL; ++p)
6811# ifdef FEAT_MBYTE
6812 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00006813 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006814 ++p;
6815 else
6816# endif
6817 if (*p == '\\')
6818 *p = '/';
6819}
6820#endif
6821
6822
6823/*
6824 * Code for automatic commands.
6825 *
6826 * Only included when "FEAT_AUTOCMD" has been defined.
6827 */
6828
6829#if defined(FEAT_AUTOCMD) || defined(PROTO)
6830
6831/*
6832 * The autocommands are stored in a list for each event.
6833 * Autocommands for the same pattern, that are consecutive, are joined
6834 * together, to avoid having to match the pattern too often.
6835 * The result is an array of Autopat lists, which point to AutoCmd lists:
6836 *
6837 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6838 * Autopat.cmds Autopat.cmds
6839 * | |
6840 * V V
6841 * AutoCmd.next AutoCmd.next
6842 * | |
6843 * V V
6844 * AutoCmd.next NULL
6845 * |
6846 * V
6847 * NULL
6848 *
6849 * first_autopat[1] --> Autopat.next --> NULL
6850 * Autopat.cmds
6851 * |
6852 * V
6853 * AutoCmd.next
6854 * |
6855 * V
6856 * NULL
6857 * etc.
6858 *
6859 * The order of AutoCmds is important, this is the order in which they were
6860 * defined and will have to be executed.
6861 */
6862typedef struct AutoCmd
6863{
6864 char_u *cmd; /* The command to be executed (NULL
6865 when command has been removed) */
6866 char nested; /* If autocommands nest here */
6867 char last; /* last command in list */
6868#ifdef FEAT_EVAL
6869 scid_T scriptID; /* script ID where defined */
6870#endif
6871 struct AutoCmd *next; /* Next AutoCmd in list */
6872} AutoCmd;
6873
6874typedef struct AutoPat
6875{
6876 int group; /* group ID */
6877 char_u *pat; /* pattern as typed (NULL when pattern
6878 has been removed) */
6879 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00006880 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006881 char allow_dirs; /* Pattern may match whole path */
6882 char last; /* last pattern for apply_autocmds() */
6883 AutoCmd *cmds; /* list of commands to do */
6884 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006885 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006886} AutoPat;
6887
6888static struct event_name
6889{
6890 char *name; /* event name */
6891 EVENT_T event; /* event number */
6892} event_names[] =
6893{
6894 {"BufAdd", EVENT_BUFADD},
6895 {"BufCreate", EVENT_BUFADD},
6896 {"BufDelete", EVENT_BUFDELETE},
6897 {"BufEnter", EVENT_BUFENTER},
6898 {"BufFilePost", EVENT_BUFFILEPOST},
6899 {"BufFilePre", EVENT_BUFFILEPRE},
6900 {"BufHidden", EVENT_BUFHIDDEN},
6901 {"BufLeave", EVENT_BUFLEAVE},
6902 {"BufNew", EVENT_BUFNEW},
6903 {"BufNewFile", EVENT_BUFNEWFILE},
6904 {"BufRead", EVENT_BUFREADPOST},
6905 {"BufReadCmd", EVENT_BUFREADCMD},
6906 {"BufReadPost", EVENT_BUFREADPOST},
6907 {"BufReadPre", EVENT_BUFREADPRE},
6908 {"BufUnload", EVENT_BUFUNLOAD},
6909 {"BufWinEnter", EVENT_BUFWINENTER},
6910 {"BufWinLeave", EVENT_BUFWINLEAVE},
6911 {"BufWipeout", EVENT_BUFWIPEOUT},
6912 {"BufWrite", EVENT_BUFWRITEPRE},
6913 {"BufWritePost", EVENT_BUFWRITEPOST},
6914 {"BufWritePre", EVENT_BUFWRITEPRE},
6915 {"BufWriteCmd", EVENT_BUFWRITECMD},
6916 {"CmdwinEnter", EVENT_CMDWINENTER},
6917 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006918 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006919 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6920 {"FileEncoding", EVENT_ENCODINGCHANGED},
6921 {"CursorHold", EVENT_CURSORHOLD},
6922 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6923 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6924 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6925 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
6926 {"FileChangedRO", EVENT_FILECHANGEDRO},
6927 {"FileReadPost", EVENT_FILEREADPOST},
6928 {"FileReadPre", EVENT_FILEREADPRE},
6929 {"FileReadCmd", EVENT_FILEREADCMD},
6930 {"FileType", EVENT_FILETYPE},
6931 {"FileWritePost", EVENT_FILEWRITEPOST},
6932 {"FileWritePre", EVENT_FILEWRITEPRE},
6933 {"FileWriteCmd", EVENT_FILEWRITECMD},
6934 {"FilterReadPost", EVENT_FILTERREADPOST},
6935 {"FilterReadPre", EVENT_FILTERREADPRE},
6936 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6937 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6938 {"FocusGained", EVENT_FOCUSGAINED},
6939 {"FocusLost", EVENT_FOCUSLOST},
6940 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6941 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006942 {"InsertChange", EVENT_INSERTCHANGE},
6943 {"InsertEnter", EVENT_INSERTENTER},
6944 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00006945 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00006946 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
6947 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006948 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00006949 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006950 {"StdinReadPost", EVENT_STDINREADPOST},
6951 {"StdinReadPre", EVENT_STDINREADPRE},
6952 {"Syntax", EVENT_SYNTAX},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00006953 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006954 {"TermChanged", EVENT_TERMCHANGED},
6955 {"TermResponse", EVENT_TERMRESPONSE},
6956 {"User", EVENT_USER},
6957 {"VimEnter", EVENT_VIMENTER},
6958 {"VimLeave", EVENT_VIMLEAVE},
6959 {"VimLeavePre", EVENT_VIMLEAVEPRE},
6960 {"WinEnter", EVENT_WINENTER},
6961 {"WinLeave", EVENT_WINLEAVE},
6962 {NULL, (EVENT_T)0}
6963};
6964
6965static AutoPat *first_autopat[NUM_EVENTS] =
6966{
6967 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6968 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6969 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6970 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006971 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6972 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006973};
6974
6975/*
6976 * struct used to keep status while executing autocommands for an event.
6977 */
6978typedef struct AutoPatCmd
6979{
6980 AutoPat *curpat; /* next AutoPat to examine */
6981 AutoCmd *nextcmd; /* next AutoCmd to execute */
6982 int group; /* group being used */
6983 char_u *fname; /* fname to match with */
6984 char_u *sfname; /* sfname to match with */
6985 char_u *tail; /* tail of fname */
6986 EVENT_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006987 int arg_bufnr; /* initially equal to <abuf>, set to zero when
6988 buf is deleted */
6989 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006990} AutoPatCmd;
6991
Bram Moolenaard6f676d2005-06-01 21:51:55 +00006992static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006993
Bram Moolenaar071d4272004-06-13 20:20:40 +00006994/*
6995 * augroups stores a list of autocmd group names.
6996 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00006997static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00006998#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
6999
7000/*
7001 * The ID of the current group. Group 0 is the default one.
7002 */
7003#define AUGROUP_DEFAULT -1 /* default autocmd group */
7004#define AUGROUP_ERROR -2 /* errornouse autocmd group */
7005#define AUGROUP_ALL -3 /* all autocmd groups */
7006static int current_augroup = AUGROUP_DEFAULT;
7007
7008static int au_need_clean = FALSE; /* need to delete marked patterns */
7009
7010static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
7011static void au_remove_pat __ARGS((AutoPat *ap));
7012static void au_remove_cmds __ARGS((AutoPat *ap));
7013static void au_cleanup __ARGS((void));
7014static int au_new_group __ARGS((char_u *name));
7015static void au_del_group __ARGS((char_u *name));
7016static int au_find_group __ARGS((char_u *name));
7017static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
7018static char_u *event_nr2name __ARGS((EVENT_T event));
7019static char_u *find_end_event __ARGS((char_u *arg, int have_group));
7020static int event_ignored __ARGS((EVENT_T event));
7021static int au_get_grouparg __ARGS((char_u **argp));
7022static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
7023static char_u *getnextac __ARGS((int c, void *cookie, int indent));
7024static 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));
7025static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7026
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007027
Bram Moolenaar071d4272004-06-13 20:20:40 +00007028static EVENT_T last_event;
7029static int last_group;
7030
7031/*
7032 * Show the autocommands for one AutoPat.
7033 */
7034 static void
7035show_autocmd(ap, event)
7036 AutoPat *ap;
7037 EVENT_T event;
7038{
7039 AutoCmd *ac;
7040
7041 /* Check for "got_int" (here and at various places below), which is set
7042 * when "q" has been hit for the "--more--" prompt */
7043 if (got_int)
7044 return;
7045 if (ap->pat == NULL) /* pattern has been removed */
7046 return;
7047
7048 msg_putchar('\n');
7049 if (got_int)
7050 return;
7051 if (event != last_event || ap->group != last_group)
7052 {
7053 if (ap->group != AUGROUP_DEFAULT)
7054 {
7055 if (AUGROUP_NAME(ap->group) == NULL)
7056 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7057 else
7058 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7059 msg_puts((char_u *)" ");
7060 }
7061 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7062 last_event = event;
7063 last_group = ap->group;
7064 msg_putchar('\n');
7065 if (got_int)
7066 return;
7067 }
7068 msg_col = 4;
7069 msg_outtrans(ap->pat);
7070
7071 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7072 {
7073 if (ac->cmd != NULL) /* skip removed commands */
7074 {
7075 if (msg_col >= 14)
7076 msg_putchar('\n');
7077 msg_col = 14;
7078 if (got_int)
7079 return;
7080 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007081#ifdef FEAT_EVAL
7082 if (p_verbose > 0)
7083 last_set_msg(ac->scriptID);
7084#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007085 if (got_int)
7086 return;
7087 if (ac->next != NULL)
7088 {
7089 msg_putchar('\n');
7090 if (got_int)
7091 return;
7092 }
7093 }
7094 }
7095}
7096
7097/*
7098 * Mark an autocommand pattern for deletion.
7099 */
7100 static void
7101au_remove_pat(ap)
7102 AutoPat *ap;
7103{
7104 vim_free(ap->pat);
7105 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007106 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007107 au_need_clean = TRUE;
7108}
7109
7110/*
7111 * Mark all commands for a pattern for deletion.
7112 */
7113 static void
7114au_remove_cmds(ap)
7115 AutoPat *ap;
7116{
7117 AutoCmd *ac;
7118
7119 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7120 {
7121 vim_free(ac->cmd);
7122 ac->cmd = NULL;
7123 }
7124 au_need_clean = TRUE;
7125}
7126
7127/*
7128 * Cleanup autocommands and patterns that have been deleted.
7129 * This is only done when not executing autocommands.
7130 */
7131 static void
7132au_cleanup()
7133{
7134 AutoPat *ap, **prev_ap;
7135 AutoCmd *ac, **prev_ac;
7136 EVENT_T event;
7137
7138 if (autocmd_busy || !au_need_clean)
7139 return;
7140
7141 /* loop over all events */
7142 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7143 event = (EVENT_T)((int)event + 1))
7144 {
7145 /* loop over all autocommand patterns */
7146 prev_ap = &(first_autopat[(int)event]);
7147 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7148 {
7149 /* loop over all commands for this pattern */
7150 prev_ac = &(ap->cmds);
7151 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7152 {
7153 /* remove the command if the pattern is to be deleted or when
7154 * the command has been marked for deletion */
7155 if (ap->pat == NULL || ac->cmd == NULL)
7156 {
7157 *prev_ac = ac->next;
7158 vim_free(ac->cmd);
7159 vim_free(ac);
7160 }
7161 else
7162 prev_ac = &(ac->next);
7163 }
7164
7165 /* remove the pattern if it has been marked for deletion */
7166 if (ap->pat == NULL)
7167 {
7168 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007169 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007170 vim_free(ap);
7171 }
7172 else
7173 prev_ap = &(ap->next);
7174 }
7175 }
7176
7177 au_need_clean = FALSE;
7178}
7179
7180/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007181 * Called when buffer is freed, to remove/invalidate related buffer-local
7182 * autocmds.
7183 */
7184 void
7185aubuflocal_remove(buf)
7186 buf_T *buf;
7187{
7188 AutoPat *ap;
7189 EVENT_T event;
7190 AutoPatCmd *apc;
7191
7192 /* invalidate currently executing autocommands */
7193 for (apc = active_apc_list; apc; apc = apc->next)
7194 if (buf->b_fnum == apc->arg_bufnr)
7195 apc->arg_bufnr = 0;
7196
7197 /* invalidate buflocals looping through events */
7198 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7199 event = (EVENT_T)((int)event + 1))
7200 /* loop over all autocommand patterns */
7201 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7202 if (ap->buflocal_nr == buf->b_fnum)
7203 {
7204 au_remove_pat(ap);
7205 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007206 {
7207 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007208 smsg((char_u *)
7209 _("auto-removing autocommand: %s <buffer=%d>"),
7210 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007211 verbose_leave();
7212 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007213 }
7214 au_cleanup();
7215}
7216
7217/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007218 * Add an autocmd group name.
7219 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7220 */
7221 static int
7222au_new_group(name)
7223 char_u *name;
7224{
7225 int i;
7226
7227 i = au_find_group(name);
7228 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
7229 {
7230 /* First try using a free entry. */
7231 for (i = 0; i < augroups.ga_len; ++i)
7232 if (AUGROUP_NAME(i) == NULL)
7233 break;
7234 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
7235 return AUGROUP_ERROR;
7236
7237 AUGROUP_NAME(i) = vim_strsave(name);
7238 if (AUGROUP_NAME(i) == NULL)
7239 return AUGROUP_ERROR;
7240 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007241 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007242 }
7243
7244 return i;
7245}
7246
7247 static void
7248au_del_group(name)
7249 char_u *name;
7250{
7251 int i;
7252
7253 i = au_find_group(name);
7254 if (i == AUGROUP_ERROR) /* the group doesn't exist */
7255 EMSG2(_("E367: No such group: \"%s\""), name);
7256 else
7257 {
7258 vim_free(AUGROUP_NAME(i));
7259 AUGROUP_NAME(i) = NULL;
7260 }
7261}
7262
7263/*
7264 * Find the ID of an autocmd group name.
7265 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7266 */
7267 static int
7268au_find_group(name)
7269 char_u *name;
7270{
7271 int i;
7272
7273 for (i = 0; i < augroups.ga_len; ++i)
7274 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
7275 return i;
7276 return AUGROUP_ERROR;
7277}
7278
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007279#if defined(FEAT_BROWSE) || defined(PROTO)
7280/*
7281 * Return TRUE if augroup "name" exists.
7282 */
7283 int
7284au_has_group(name)
7285 char_u *name;
7286{
7287 return au_find_group(name) != AUGROUP_ERROR;
7288}
7289#endif
7290
Bram Moolenaar071d4272004-06-13 20:20:40 +00007291/*
7292 * ":augroup {name}".
7293 */
7294 void
7295do_augroup(arg, del_group)
7296 char_u *arg;
7297 int del_group;
7298{
7299 int i;
7300
7301 if (del_group)
7302 {
7303 if (*arg == NUL)
7304 EMSG(_(e_argreq));
7305 else
7306 au_del_group(arg);
7307 }
7308 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
7309 current_augroup = AUGROUP_DEFAULT;
7310 else if (*arg) /* ":aug xxx": switch to group xxx */
7311 {
7312 i = au_new_group(arg);
7313 if (i != AUGROUP_ERROR)
7314 current_augroup = i;
7315 }
7316 else /* ":aug": list the group names */
7317 {
7318 msg_start();
7319 for (i = 0; i < augroups.ga_len; ++i)
7320 {
7321 if (AUGROUP_NAME(i) != NULL)
7322 {
7323 msg_puts(AUGROUP_NAME(i));
7324 msg_puts((char_u *)" ");
7325 }
7326 }
7327 msg_clr_eos();
7328 msg_end();
7329 }
7330}
7331
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007332#if defined(EXITFREE) || defined(PROTO)
7333 void
7334free_all_autocmds()
7335{
7336 for (current_augroup = -1; current_augroup < augroups.ga_len;
7337 ++current_augroup)
7338 do_autocmd((char_u *)"", TRUE);
7339 ga_clear_strings(&augroups);
7340}
7341#endif
7342
Bram Moolenaar071d4272004-06-13 20:20:40 +00007343/*
7344 * Return the event number for event name "start".
7345 * Return NUM_EVENTS if the event name was not found.
7346 * Return a pointer to the next event name in "end".
7347 */
7348 static EVENT_T
7349event_name2nr(start, end)
7350 char_u *start;
7351 char_u **end;
7352{
7353 char_u *p;
7354 int i;
7355 int len;
7356
7357 /* the event name ends with end of line, a blank or a comma */
7358 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7359 ;
7360 for (i = 0; event_names[i].name != NULL; ++i)
7361 {
7362 len = (int)STRLEN(event_names[i].name);
7363 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7364 break;
7365 }
7366 if (*p == ',')
7367 ++p;
7368 *end = p;
7369 if (event_names[i].name == NULL)
7370 return NUM_EVENTS;
7371 return event_names[i].event;
7372}
7373
7374/*
7375 * Return the name for event "event".
7376 */
7377 static char_u *
7378event_nr2name(event)
7379 EVENT_T event;
7380{
7381 int i;
7382
7383 for (i = 0; event_names[i].name != NULL; ++i)
7384 if (event_names[i].event == event)
7385 return (char_u *)event_names[i].name;
7386 return (char_u *)"Unknown";
7387}
7388
7389/*
7390 * Scan over the events. "*" stands for all events.
7391 */
7392 static char_u *
7393find_end_event(arg, have_group)
7394 char_u *arg;
7395 int have_group; /* TRUE when group name was found */
7396{
7397 char_u *pat;
7398 char_u *p;
7399
7400 if (*arg == '*')
7401 {
7402 if (arg[1] && !vim_iswhite(arg[1]))
7403 {
7404 EMSG2(_("E215: Illegal character after *: %s"), arg);
7405 return NULL;
7406 }
7407 pat = arg + 1;
7408 }
7409 else
7410 {
7411 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7412 {
7413 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7414 {
7415 if (have_group)
7416 EMSG2(_("E216: No such event: %s"), pat);
7417 else
7418 EMSG2(_("E216: No such group or event: %s"), pat);
7419 return NULL;
7420 }
7421 }
7422 }
7423 return pat;
7424}
7425
7426/*
7427 * Return TRUE if "event" is included in 'eventignore'.
7428 */
7429 static int
7430event_ignored(event)
7431 EVENT_T event;
7432{
7433 char_u *p = p_ei;
7434
7435 if (STRICMP(p_ei, "all") == 0)
7436 return TRUE;
7437
7438 while (*p)
7439 if (event_name2nr(p, &p) == event)
7440 return TRUE;
7441
7442 return FALSE;
7443}
7444
7445/*
7446 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7447 */
7448 int
7449check_ei()
7450{
7451 char_u *p = p_ei;
7452
7453 if (STRICMP(p_ei, "all") == 0)
7454 return OK;
7455
7456 while (*p)
7457 if (event_name2nr(p, &p) == NUM_EVENTS)
7458 return FAIL;
7459
7460 return OK;
7461}
7462
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007463# if defined(FEAT_SYN_HL) || defined(PROTO)
7464
7465/*
7466 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7467 * buffer loaded into the window. "what" must start with a comma.
7468 * Returns the old value of 'eventignore' in allocated memory.
7469 */
7470 char_u *
7471au_event_disable(what)
7472 char *what;
7473{
7474 char_u *new_ei;
7475 char_u *save_ei;
7476
7477 save_ei = vim_strsave(p_ei);
7478 if (save_ei != NULL)
7479 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00007480 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007481 if (new_ei != NULL)
7482 {
7483 STRCAT(new_ei, what);
7484 set_string_option_direct((char_u *)"ei", -1, new_ei, OPT_FREE);
7485 vim_free(new_ei);
7486 }
7487 }
7488 return save_ei;
7489}
7490
7491 void
7492au_event_restore(old_ei)
7493 char_u *old_ei;
7494{
7495 if (old_ei != NULL)
7496 {
7497 set_string_option_direct((char_u *)"ei", -1, old_ei, OPT_FREE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007498 vim_free(old_ei);
7499 }
7500}
7501# endif /* FEAT_SYN_HL */
7502
Bram Moolenaar071d4272004-06-13 20:20:40 +00007503/*
7504 * do_autocmd() -- implements the :autocmd command. Can be used in the
7505 * following ways:
7506 *
7507 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7508 * will be automatically executed for <event>
7509 * when editing a file matching <pat>, in
7510 * the current group.
7511 * :autocmd <event> <pat> Show the auto-commands associated with
7512 * <event> and <pat>.
7513 * :autocmd <event> Show the auto-commands associated with
7514 * <event>.
7515 * :autocmd Show all auto-commands.
7516 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7517 * <event> and <pat>, and add the command
7518 * <cmd>, for the current group.
7519 * :autocmd! <event> <pat> Remove all auto-commands associated with
7520 * <event> and <pat> for the current group.
7521 * :autocmd! <event> Remove all auto-commands associated with
7522 * <event> for the current group.
7523 * :autocmd! Remove ALL auto-commands for the current
7524 * group.
7525 *
7526 * Multiple events and patterns may be given separated by commas. Here are
7527 * some examples:
7528 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7529 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7530 *
7531 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00007532 *
7533 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007534 */
7535 void
7536do_autocmd(arg, forceit)
7537 char_u *arg;
7538 int forceit;
7539{
7540 char_u *pat;
7541 char_u *envpat = NULL;
7542 char_u *cmd;
7543 EVENT_T event;
7544 int need_free = FALSE;
7545 int nested = FALSE;
7546 int group;
7547
7548 /*
7549 * Check for a legal group name. If not, use AUGROUP_ALL.
7550 */
7551 group = au_get_grouparg(&arg);
7552 if (arg == NULL) /* out of memory */
7553 return;
7554
7555 /*
7556 * Scan over the events.
7557 * If we find an illegal name, return here, don't do anything.
7558 */
7559 pat = find_end_event(arg, group != AUGROUP_ALL);
7560 if (pat == NULL)
7561 return;
7562
7563 /*
7564 * Scan over the pattern. Put a NUL at the end.
7565 */
7566 pat = skipwhite(pat);
7567 cmd = pat;
7568 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7569 cmd++;
7570 if (*cmd)
7571 *cmd++ = NUL;
7572
7573 /* Expand environment variables in the pattern. Set 'shellslash', we want
7574 * forward slashes here. */
7575 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7576 {
7577#ifdef BACKSLASH_IN_FILENAME
7578 int p_ssl_save = p_ssl;
7579
7580 p_ssl = TRUE;
7581#endif
7582 envpat = expand_env_save(pat);
7583#ifdef BACKSLASH_IN_FILENAME
7584 p_ssl = p_ssl_save;
7585#endif
7586 if (envpat != NULL)
7587 pat = envpat;
7588 }
7589
7590 /*
7591 * Check for "nested" flag.
7592 */
7593 cmd = skipwhite(cmd);
7594 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7595 {
7596 nested = TRUE;
7597 cmd = skipwhite(cmd + 6);
7598 }
7599
7600 /*
7601 * Find the start of the commands.
7602 * Expand <sfile> in it.
7603 */
7604 if (*cmd != NUL)
7605 {
7606 cmd = expand_sfile(cmd);
7607 if (cmd == NULL) /* some error */
7608 return;
7609 need_free = TRUE;
7610 }
7611
7612 /*
7613 * Print header when showing autocommands.
7614 */
7615 if (!forceit && *cmd == NUL)
7616 {
7617 /* Highlight title */
7618 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7619 }
7620
7621 /*
7622 * Loop over the events.
7623 */
7624 last_event = (EVENT_T)-1; /* for listing the event name */
7625 last_group = AUGROUP_ERROR; /* for listing the group name */
7626 if (*arg == '*' || *arg == NUL)
7627 {
7628 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7629 event = (EVENT_T)((int)event + 1))
7630 if (do_autocmd_event(event, pat,
7631 nested, cmd, forceit, group) == FAIL)
7632 break;
7633 }
7634 else
7635 {
7636 while (*arg && !vim_iswhite(*arg))
7637 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7638 nested, cmd, forceit, group) == FAIL)
7639 break;
7640 }
7641
7642 if (need_free)
7643 vim_free(cmd);
7644 vim_free(envpat);
7645}
7646
7647/*
7648 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7649 * The "argp" argument is advanced to the following argument.
7650 *
7651 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7652 */
7653 static int
7654au_get_grouparg(argp)
7655 char_u **argp;
7656{
7657 char_u *group_name;
7658 char_u *p;
7659 char_u *arg = *argp;
7660 int group = AUGROUP_ALL;
7661
7662 p = skiptowhite(arg);
7663 if (p > arg)
7664 {
7665 group_name = vim_strnsave(arg, (int)(p - arg));
7666 if (group_name == NULL) /* out of memory */
7667 return AUGROUP_ERROR;
7668 group = au_find_group(group_name);
7669 if (group == AUGROUP_ERROR)
7670 group = AUGROUP_ALL; /* no match, use all groups */
7671 else
7672 *argp = skipwhite(p); /* match, skip over group name */
7673 vim_free(group_name);
7674 }
7675 return group;
7676}
7677
7678/*
7679 * do_autocmd() for one event.
7680 * If *pat == NUL do for all patterns.
7681 * If *cmd == NUL show entries.
7682 * If forceit == TRUE delete entries.
7683 * If group is not AUGROUP_ALL, only use this group.
7684 */
7685 static int
7686do_autocmd_event(event, pat, nested, cmd, forceit, group)
7687 EVENT_T event;
7688 char_u *pat;
7689 int nested;
7690 char_u *cmd;
7691 int forceit;
7692 int group;
7693{
7694 AutoPat *ap;
7695 AutoPat **prev_ap;
7696 AutoCmd *ac;
7697 AutoCmd **prev_ac;
7698 int brace_level;
7699 char_u *endpat;
7700 int findgroup;
7701 int allgroups;
7702 int patlen;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007703 int is_buflocal;
7704 int buflocal_nr;
7705 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007706
7707 if (group == AUGROUP_ALL)
7708 findgroup = current_augroup;
7709 else
7710 findgroup = group;
7711 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7712
7713 /*
7714 * Show or delete all patterns for an event.
7715 */
7716 if (*pat == NUL)
7717 {
7718 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7719 {
7720 if (forceit) /* delete the AutoPat, if it's in the current group */
7721 {
7722 if (ap->group == findgroup)
7723 au_remove_pat(ap);
7724 }
7725 else if (group == AUGROUP_ALL || ap->group == group)
7726 show_autocmd(ap, event);
7727 }
7728 }
7729
7730 /*
7731 * Loop through all the specified patterns.
7732 */
7733 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7734 {
7735 /*
7736 * Find end of the pattern.
7737 * Watch out for a comma in braces, like "*.\{obj,o\}".
7738 */
7739 brace_level = 0;
7740 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7741 || endpat[-1] == '\\'); ++endpat)
7742 {
7743 if (*endpat == '{')
7744 brace_level++;
7745 else if (*endpat == '}')
7746 brace_level--;
7747 }
7748 if (pat == endpat) /* ignore single comma */
7749 continue;
7750 patlen = (int)(endpat - pat);
7751
7752 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007753 * detect special <buflocal[=X]> buffer-local patterns
7754 */
7755 is_buflocal = FALSE;
7756 buflocal_nr = 0;
7757
7758 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
7759 && pat[patlen - 1] == '>')
7760 {
7761 /* Error will be printed only for addition. printing and removing
7762 * will proceed silently. */
7763 is_buflocal = TRUE;
7764 if (patlen == 8)
7765 buflocal_nr = curbuf->b_fnum;
7766 else if (patlen > 9 && pat[7] == '=')
7767 {
7768 /* <buffer=abuf> */
7769 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
7770 buflocal_nr = autocmd_bufnr;
7771 /* <buffer=123> */
7772 else if (skipdigits(pat + 8) == pat + patlen - 1)
7773 buflocal_nr = atoi((char *)pat + 8);
7774 }
7775 }
7776
7777 if (is_buflocal)
7778 {
7779 /* normalize pat into standard "<buffer>#N" form */
7780 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
7781 pat = buflocal_pat; /* can modify pat and patlen */
7782 patlen = STRLEN(buflocal_pat); /* but not endpat */
7783 }
7784
7785 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007786 * Find AutoPat entries with this pattern.
7787 */
7788 prev_ap = &first_autopat[(int)event];
7789 while ((ap = *prev_ap) != NULL)
7790 {
7791 if (ap->pat != NULL)
7792 {
7793 /* Accept a pattern when:
7794 * - a group was specified and it's that group, or a group was
7795 * not specified and it's the current group, or a group was
7796 * not specified and we are listing
7797 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007798 * - the pattern matches.
7799 * For <buffer[=X]>, this condition works because we normalize
7800 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007801 */
7802 if ((allgroups || ap->group == findgroup)
7803 && ap->patlen == patlen
7804 && STRNCMP(pat, ap->pat, patlen) == 0)
7805 {
7806 /*
7807 * Remove existing autocommands.
7808 * If adding any new autocmd's for this AutoPat, don't
7809 * delete the pattern from the autopat list, append to
7810 * this list.
7811 */
7812 if (forceit)
7813 {
7814 if (*cmd != NUL && ap->next == NULL)
7815 {
7816 au_remove_cmds(ap);
7817 break;
7818 }
7819 au_remove_pat(ap);
7820 }
7821
7822 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007823 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00007824 */
7825 else if (*cmd == NUL)
7826 show_autocmd(ap, event);
7827
7828 /*
7829 * Add autocmd to this autopat, if it's the last one.
7830 */
7831 else if (ap->next == NULL)
7832 break;
7833 }
7834 }
7835 prev_ap = &ap->next;
7836 }
7837
7838 /*
7839 * Add a new command.
7840 */
7841 if (*cmd != NUL)
7842 {
7843 /*
7844 * If the pattern we want to add a command to does appear at the
7845 * end of the list (or not is not in the list at all), add the
7846 * pattern at the end of the list.
7847 */
7848 if (ap == NULL)
7849 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007850 /* refuse to add buffer-local ap if buffer number is invalid */
7851 if (is_buflocal && (buflocal_nr == 0
7852 || buflist_findnr(buflocal_nr) == NULL))
7853 {
7854 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
7855 buflocal_nr);
7856 return FAIL;
7857 }
7858
Bram Moolenaar071d4272004-06-13 20:20:40 +00007859 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7860 if (ap == NULL)
7861 return FAIL;
7862 ap->pat = vim_strnsave(pat, patlen);
7863 ap->patlen = patlen;
7864 if (ap->pat == NULL)
7865 {
7866 vim_free(ap);
7867 return FAIL;
7868 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007869
7870 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007871 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007872 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007873 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007874 }
7875 else
7876 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00007877 char_u *reg_pat;
7878
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007879 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007880 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007881 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007882 if (reg_pat != NULL)
7883 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007884 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007885 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007886 {
7887 vim_free(ap->pat);
7888 vim_free(ap);
7889 return FAIL;
7890 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007891 }
7892 ap->cmds = NULL;
7893 *prev_ap = ap;
7894 ap->next = NULL;
7895 if (group == AUGROUP_ALL)
7896 ap->group = current_augroup;
7897 else
7898 ap->group = group;
7899 }
7900
7901 /*
7902 * Add the autocmd at the end of the AutoCmd list.
7903 */
7904 prev_ac = &(ap->cmds);
7905 while ((ac = *prev_ac) != NULL)
7906 prev_ac = &ac->next;
7907 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7908 if (ac == NULL)
7909 return FAIL;
7910 ac->cmd = vim_strsave(cmd);
7911#ifdef FEAT_EVAL
7912 ac->scriptID = current_SID;
7913#endif
7914 if (ac->cmd == NULL)
7915 {
7916 vim_free(ac);
7917 return FAIL;
7918 }
7919 ac->next = NULL;
7920 *prev_ac = ac;
7921 ac->nested = nested;
7922 }
7923 }
7924
7925 au_cleanup(); /* may really delete removed patterns/commands now */
7926 return OK;
7927}
7928
7929/*
7930 * Implementation of ":doautocmd [group] event [fname]".
7931 * Return OK for success, FAIL for failure;
7932 */
7933 int
7934do_doautocmd(arg, do_msg)
7935 char_u *arg;
7936 int do_msg; /* give message for no matching autocmds? */
7937{
7938 char_u *fname;
7939 int nothing_done = TRUE;
7940 int group;
7941
7942 /*
7943 * Check for a legal group name. If not, use AUGROUP_ALL.
7944 */
7945 group = au_get_grouparg(&arg);
7946 if (arg == NULL) /* out of memory */
7947 return FAIL;
7948
7949 if (*arg == '*')
7950 {
7951 EMSG(_("E217: Can't execute autocommands for ALL events"));
7952 return FAIL;
7953 }
7954
7955 /*
7956 * Scan over the events.
7957 * If we find an illegal name, return here, don't do anything.
7958 */
7959 fname = find_end_event(arg, group != AUGROUP_ALL);
7960 if (fname == NULL)
7961 return FAIL;
7962
7963 fname = skipwhite(fname);
7964
7965 /*
7966 * Loop over the events.
7967 */
7968 while (*arg && !vim_iswhite(*arg))
7969 if (apply_autocmds_group(event_name2nr(arg, &arg),
7970 fname, NULL, TRUE, group, curbuf, NULL))
7971 nothing_done = FALSE;
7972
7973 if (nothing_done && do_msg)
7974 MSG(_("No matching autocommands"));
7975
7976#ifdef FEAT_EVAL
7977 return aborting() ? FAIL : OK;
7978#else
7979 return OK;
7980#endif
7981}
7982
7983/*
7984 * ":doautoall": execute autocommands for each loaded buffer.
7985 */
7986 void
7987ex_doautoall(eap)
7988 exarg_T *eap;
7989{
7990 int retval;
7991 aco_save_T aco;
7992 buf_T *buf;
7993
7994 /*
7995 * This is a bit tricky: For some commands curwin->w_buffer needs to be
7996 * equal to curbuf, but for some buffers there may not be a window.
7997 * So we change the buffer for the current window for a moment. This
7998 * gives problems when the autocommands make changes to the list of
7999 * buffers or windows...
8000 */
8001 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8002 {
8003 if (curbuf->b_ml.ml_mfp != NULL)
8004 {
8005 /* find a window for this buffer and save some values */
8006 aucmd_prepbuf(&aco, buf);
8007
8008 /* execute the autocommands for this buffer */
8009 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00008010 do_modelines(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008011
8012 /* restore the current window */
8013 aucmd_restbuf(&aco);
8014
8015 /* stop if there is some error or buffer was deleted */
8016 if (retval == FAIL || !buf_valid(buf))
8017 break;
8018 }
8019 }
8020
8021 check_cursor(); /* just in case lines got deleted */
8022}
8023
8024/*
8025 * Prepare for executing autocommands for (hidden) buffer "buf".
8026 * Search a window for the current buffer. Save the cursor position and
8027 * screen offset.
8028 * Set "curbuf" and "curwin" to match "buf".
8029 */
8030 void
8031aucmd_prepbuf(aco, buf)
8032 aco_save_T *aco; /* structure to save values in */
8033 buf_T *buf; /* new curbuf */
8034{
8035 win_T *win;
8036
8037 aco->new_curbuf = buf;
8038
8039 /* Find a window that is for the new buffer */
8040 if (buf == curbuf) /* be quick when buf is curbuf */
8041 win = curwin;
8042 else
8043#ifdef FEAT_WINDOWS
8044 for (win = firstwin; win != NULL; win = win->w_next)
8045 if (win->w_buffer == buf)
8046 break;
8047#else
8048 win = NULL;
8049#endif
8050
8051 /*
8052 * Prefer to use an existing window for the buffer, it has the least side
8053 * effects (esp. if "buf" is curbuf).
8054 * Otherwise, use curwin for "buf". It might make some items in the
8055 * window invalid. At least save the cursor and topline.
8056 */
8057 if (win != NULL)
8058 {
8059 /* there is a window for "buf", make it the curwin */
8060 aco->save_curwin = curwin;
8061 curwin = win;
8062 aco->save_buf = win->w_buffer;
8063 aco->new_curwin = win;
8064 }
8065 else
8066 {
8067 /* there is no window for "buf", use curwin */
8068 aco->save_curwin = NULL;
8069 aco->save_buf = curbuf;
8070 --curbuf->b_nwindows;
8071 curwin->w_buffer = buf;
8072 ++buf->b_nwindows;
8073
8074 /* save cursor and topline, set them to safe values */
8075 aco->save_cursor = curwin->w_cursor;
8076 curwin->w_cursor.lnum = 1;
8077 curwin->w_cursor.col = 0;
8078 aco->save_topline = curwin->w_topline;
8079 curwin->w_topline = 1;
8080#ifdef FEAT_DIFF
8081 aco->save_topfill = curwin->w_topfill;
8082 curwin->w_topfill = 0;
8083#endif
8084 }
8085
8086 curbuf = buf;
8087}
8088
8089/*
8090 * Cleanup after executing autocommands for a (hidden) buffer.
8091 * Restore the window as it was (if possible).
8092 */
8093 void
8094aucmd_restbuf(aco)
8095 aco_save_T *aco; /* structure holding saved values */
8096{
8097 if (aco->save_curwin != NULL)
8098 {
8099 /* restore curwin */
8100#ifdef FEAT_WINDOWS
8101 if (win_valid(aco->save_curwin))
8102#endif
8103 {
8104 /* restore the buffer which was previously edited by curwin, if
8105 * it's still the same window and it's valid */
8106 if (curwin == aco->new_curwin
8107 && buf_valid(aco->save_buf)
8108 && aco->save_buf->b_ml.ml_mfp != NULL)
8109 {
8110 --curbuf->b_nwindows;
8111 curbuf = aco->save_buf;
8112 curwin->w_buffer = curbuf;
8113 ++curbuf->b_nwindows;
8114 }
8115
8116 curwin = aco->save_curwin;
8117 curbuf = curwin->w_buffer;
8118 }
8119 }
8120 else
8121 {
8122 /* restore buffer for curwin if it still exists and is loaded */
8123 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
8124 {
8125 --curbuf->b_nwindows;
8126 curbuf = aco->save_buf;
8127 curwin->w_buffer = curbuf;
8128 ++curbuf->b_nwindows;
8129 curwin->w_cursor = aco->save_cursor;
8130 check_cursor();
8131 /* check topline < line_count, in case lines got deleted */
8132 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
8133 {
8134 curwin->w_topline = aco->save_topline;
8135#ifdef FEAT_DIFF
8136 curwin->w_topfill = aco->save_topfill;
8137#endif
8138 }
8139 else
8140 {
8141 curwin->w_topline = curbuf->b_ml.ml_line_count;
8142#ifdef FEAT_DIFF
8143 curwin->w_topfill = 0;
8144#endif
8145 }
8146 }
8147 }
8148}
8149
8150static int autocmd_nested = FALSE;
8151
8152/*
8153 * Execute autocommands for "event" and file name "fname".
8154 * Return TRUE if some commands were executed.
8155 */
8156 int
8157apply_autocmds(event, fname, fname_io, force, buf)
8158 EVENT_T event;
8159 char_u *fname; /* NULL or empty means use actual file name */
8160 char_u *fname_io; /* fname to use for <afile> on cmdline */
8161 int force; /* when TRUE, ignore autocmd_busy */
8162 buf_T *buf; /* buffer for <abuf> */
8163{
8164 return apply_autocmds_group(event, fname, fname_io, force,
8165 AUGROUP_ALL, buf, NULL);
8166}
8167
8168/*
8169 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
8170 * setting v:filearg.
8171 */
8172 static int
8173apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
8174 EVENT_T event;
8175 char_u *fname;
8176 char_u *fname_io;
8177 int force;
8178 buf_T *buf;
8179 exarg_T *eap;
8180{
8181 return apply_autocmds_group(event, fname, fname_io, force,
8182 AUGROUP_ALL, buf, eap);
8183}
8184
8185/*
8186 * Like apply_autocmds(), but handles the caller's retval. If the script
8187 * processing is being aborted or if retval is FAIL when inside a try
8188 * conditional, no autocommands are executed. If otherwise the autocommands
8189 * cause the script to be aborted, retval is set to FAIL.
8190 */
8191 int
8192apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
8193 EVENT_T event;
8194 char_u *fname; /* NULL or empty means use actual file name */
8195 char_u *fname_io; /* fname to use for <afile> on cmdline */
8196 int force; /* when TRUE, ignore autocmd_busy */
8197 buf_T *buf; /* buffer for <abuf> */
8198 int *retval; /* pointer to caller's retval */
8199{
8200 int did_cmd;
8201
Bram Moolenaar1e015462005-09-25 22:16:38 +00008202#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008203 if (should_abort(*retval))
8204 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00008205#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008206
8207 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
8208 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008209 if (did_cmd
8210#ifdef FEAT_EVAL
8211 && aborting()
8212#endif
8213 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008214 *retval = FAIL;
8215 return did_cmd;
8216}
8217
8218#if defined(FEAT_AUTOCMD) || defined(PROTO)
Bram Moolenaard35f9712005-12-18 22:02:33 +00008219/*
8220 * Return TRUE when there is a CursorHold autocommand defined.
8221 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008222 int
8223has_cursorhold()
8224{
8225 return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
8226}
Bram Moolenaard35f9712005-12-18 22:02:33 +00008227
8228/*
8229 * Return TRUE if the CursorHold event can be triggered.
8230 */
8231 int
8232trigger_cursorhold()
8233{
8234 return (!did_cursorhold
8235 && has_cursorhold()
8236 && !Recording
8237 && get_real_state() == NORMAL_BUSY);
8238}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008239#endif
8240
8241 static int
8242apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
8243 EVENT_T event;
8244 char_u *fname; /* NULL or empty means use actual file name */
8245 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
8246 use fname */
8247 int force; /* when TRUE, ignore autocmd_busy */
8248 int group; /* group ID, or AUGROUP_ALL */
8249 buf_T *buf; /* buffer for <abuf> */
8250 exarg_T *eap; /* command arguments */
8251{
8252 char_u *sfname = NULL; /* short file name */
8253 char_u *tail;
8254 int save_changed;
8255 buf_T *old_curbuf;
8256 int retval = FALSE;
8257 char_u *save_sourcing_name;
8258 linenr_T save_sourcing_lnum;
8259 char_u *save_autocmd_fname;
8260 int save_autocmd_bufnr;
8261 char_u *save_autocmd_match;
8262 int save_autocmd_busy;
8263 int save_autocmd_nested;
8264 static int nesting = 0;
8265 AutoPatCmd patcmd;
8266 AutoPat *ap;
8267#ifdef FEAT_EVAL
8268 scid_T save_current_SID;
8269 void *save_funccalp;
8270 char_u *save_cmdarg;
8271 long save_cmdbang;
8272#endif
8273 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00008274#ifdef FEAT_PROFILE
8275 proftime_T wait_time;
8276#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008277
8278 /*
8279 * Quickly return if there are no autocommands for this event or
8280 * autocommands are blocked.
8281 */
8282 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008283 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008284
8285 /*
8286 * When autocommands are busy, new autocommands are only executed when
8287 * explicitly enabled with the "nested" flag.
8288 */
8289 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008290 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008291
8292#ifdef FEAT_EVAL
8293 /*
8294 * Quickly return when immdediately aborting on error, or when an interrupt
8295 * occurred or an exception was thrown but not caught.
8296 */
8297 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008298 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008299#endif
8300
8301 /*
8302 * FileChangedShell never nests, because it can create an endless loop.
8303 */
8304 if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008305 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008306
8307 /*
8308 * Ignore events in 'eventignore'.
8309 */
8310 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008311 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008312
8313 /*
8314 * Allow nesting of autocommands, but restrict the depth, because it's
8315 * possible to create an endless loop.
8316 */
8317 if (nesting == 10)
8318 {
8319 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008320 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008321 }
8322
8323 /*
8324 * Check if these autocommands are disabled. Used when doing ":all" or
8325 * ":ball".
8326 */
8327 if ( (autocmd_no_enter
8328 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
8329 || (autocmd_no_leave
8330 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008331 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008332
8333 /*
8334 * Save the autocmd_* variables and info about the current buffer.
8335 */
8336 save_autocmd_fname = autocmd_fname;
8337 save_autocmd_bufnr = autocmd_bufnr;
8338 save_autocmd_match = autocmd_match;
8339 save_autocmd_busy = autocmd_busy;
8340 save_autocmd_nested = autocmd_nested;
8341 save_changed = curbuf->b_changed;
8342 old_curbuf = curbuf;
8343
8344 /*
8345 * Set the file name to be used for <afile>.
8346 */
8347 if (fname_io == NULL)
8348 {
8349 if (fname != NULL && *fname != NUL)
8350 autocmd_fname = fname;
8351 else if (buf != NULL)
8352 autocmd_fname = buf->b_fname;
8353 else
8354 autocmd_fname = NULL;
8355 }
8356 else
8357 autocmd_fname = fname_io;
8358
8359 /*
8360 * Set the buffer number to be used for <abuf>.
8361 */
8362 if (buf == NULL)
8363 autocmd_bufnr = 0;
8364 else
8365 autocmd_bufnr = buf->b_fnum;
8366
8367 /*
8368 * When the file name is NULL or empty, use the file name of buffer "buf".
8369 * Always use the full path of the file name to match with, in case
8370 * "allow_dirs" is set.
8371 */
8372 if (fname == NULL || *fname == NUL)
8373 {
8374 if (buf == NULL)
8375 fname = NULL;
8376 else
8377 {
8378#ifdef FEAT_SYN_HL
8379 if (event == EVENT_SYNTAX)
8380 fname = buf->b_p_syn;
8381 else
8382#endif
8383 if (event == EVENT_FILETYPE)
8384 fname = buf->b_p_ft;
8385 else
8386 {
8387 if (buf->b_sfname != NULL)
8388 sfname = vim_strsave(buf->b_sfname);
8389 fname = buf->b_ffname;
8390 }
8391 }
8392 if (fname == NULL)
8393 fname = (char_u *)"";
8394 fname = vim_strsave(fname); /* make a copy, so we can change it */
8395 }
8396 else
8397 {
8398 sfname = vim_strsave(fname);
Bram Moolenaar7c626922005-02-07 22:01:03 +00008399 /* Don't try expanding FileType, Syntax, WindowID or QuickFixCmd* */
8400 if (event == EVENT_FILETYPE
8401 || event == EVENT_SYNTAX
8402 || event == EVENT_REMOTEREPLY
8403 || event == EVENT_QUICKFIXCMDPRE
8404 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008405 fname = vim_strsave(fname);
8406 else
8407 fname = FullName_save(fname, FALSE);
8408 }
8409 if (fname == NULL) /* out of memory */
8410 {
8411 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008412 retval = FALSE;
8413 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008414 }
8415
8416#ifdef BACKSLASH_IN_FILENAME
8417 /*
8418 * Replace all backslashes with forward slashes. This makes the
8419 * autocommand patterns portable between Unix and MS-DOS.
8420 */
8421 if (sfname != NULL)
8422 forward_slash(sfname);
8423 forward_slash(fname);
8424#endif
8425
8426#ifdef VMS
8427 /* remove version for correct match */
8428 if (sfname != NULL)
8429 vms_remove_version(sfname);
8430 vms_remove_version(fname);
8431#endif
8432
8433 /*
8434 * Set the name to be used for <amatch>.
8435 */
8436 autocmd_match = fname;
8437
8438
8439 /* Don't redraw while doing auto commands. */
8440 ++RedrawingDisabled;
8441 save_sourcing_name = sourcing_name;
8442 sourcing_name = NULL; /* don't free this one */
8443 save_sourcing_lnum = sourcing_lnum;
8444 sourcing_lnum = 0; /* no line number here */
8445
8446#ifdef FEAT_EVAL
8447 save_current_SID = current_SID;
8448
Bram Moolenaar05159a02005-02-26 23:04:13 +00008449# ifdef FEAT_PROFILE
8450 if (do_profiling)
8451 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
8452# endif
8453
Bram Moolenaar071d4272004-06-13 20:20:40 +00008454 /* Don't use local function variables, if called from a function */
8455 save_funccalp = save_funccal();
8456#endif
8457
8458 /*
8459 * When starting to execute autocommands, save the search patterns.
8460 */
8461 if (!autocmd_busy)
8462 {
8463 save_search_patterns();
8464 saveRedobuff();
8465 did_filetype = keep_filetype;
8466 }
8467
8468 /*
8469 * Note that we are applying autocmds. Some commands need to know.
8470 */
8471 autocmd_busy = TRUE;
8472 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
8473 ++nesting; /* see matching decrement below */
8474
8475 /* Remember that FileType was triggered. Used for did_filetype(). */
8476 if (event == EVENT_FILETYPE)
8477 did_filetype = TRUE;
8478
8479 tail = gettail(fname);
8480
8481 /* Find first autocommand that matches */
8482 patcmd.curpat = first_autopat[(int)event];
8483 patcmd.nextcmd = NULL;
8484 patcmd.group = group;
8485 patcmd.fname = fname;
8486 patcmd.sfname = sfname;
8487 patcmd.tail = tail;
8488 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008489 patcmd.arg_bufnr = autocmd_bufnr;
8490 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008491 auto_next_pat(&patcmd, FALSE);
8492
8493 /* found one, start executing the autocommands */
8494 if (patcmd.curpat != NULL)
8495 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008496 /* add to active_apc_list */
8497 patcmd.next = active_apc_list;
8498 active_apc_list = &patcmd;
8499
Bram Moolenaar071d4272004-06-13 20:20:40 +00008500#ifdef FEAT_EVAL
8501 /* set v:cmdarg (only when there is a matching pattern) */
8502 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
8503 if (eap != NULL)
8504 {
8505 save_cmdarg = set_cmdarg(eap, NULL);
8506 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
8507 }
8508 else
8509 save_cmdarg = NULL; /* avoid gcc warning */
8510#endif
8511 retval = TRUE;
8512 /* mark the last pattern, to avoid an endless loop when more patterns
8513 * are added when executing autocommands */
8514 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8515 ap->last = FALSE;
8516 ap->last = TRUE;
8517 check_lnums(TRUE); /* make sure cursor and topline are valid */
8518 do_cmdline(NULL, getnextac, (void *)&patcmd,
8519 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8520#ifdef FEAT_EVAL
8521 if (eap != NULL)
8522 {
8523 (void)set_cmdarg(NULL, save_cmdarg);
8524 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8525 }
8526#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008527 /* delete from active_apc_list */
8528 if (active_apc_list == &patcmd) /* just in case */
8529 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008530 }
8531
8532 --RedrawingDisabled;
8533 autocmd_busy = save_autocmd_busy;
8534 filechangeshell_busy = FALSE;
8535 autocmd_nested = save_autocmd_nested;
8536 vim_free(sourcing_name);
8537 sourcing_name = save_sourcing_name;
8538 sourcing_lnum = save_sourcing_lnum;
8539 autocmd_fname = save_autocmd_fname;
8540 autocmd_bufnr = save_autocmd_bufnr;
8541 autocmd_match = save_autocmd_match;
8542#ifdef FEAT_EVAL
8543 current_SID = save_current_SID;
8544 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00008545# ifdef FEAT_PROFILE
8546 if (do_profiling)
8547 prof_child_exit(&wait_time);
8548# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008549#endif
8550 vim_free(fname);
8551 vim_free(sfname);
8552 --nesting; /* see matching increment above */
8553
8554 /*
8555 * When stopping to execute autocommands, restore the search patterns and
8556 * the redo buffer.
8557 */
8558 if (!autocmd_busy)
8559 {
8560 restore_search_patterns();
8561 restoreRedobuff();
8562 did_filetype = FALSE;
8563 }
8564
8565 /*
8566 * Some events don't set or reset the Changed flag.
8567 * Check if still in the same buffer!
8568 */
8569 if (curbuf == old_curbuf
8570 && (event == EVENT_BUFREADPOST
8571 || event == EVENT_BUFWRITEPOST
8572 || event == EVENT_FILEAPPENDPOST
8573 || event == EVENT_VIMLEAVE
8574 || event == EVENT_VIMLEAVEPRE))
8575 {
8576#ifdef FEAT_TITLE
8577 if (curbuf->b_changed != save_changed)
8578 need_maketitle = TRUE;
8579#endif
8580 curbuf->b_changed = save_changed;
8581 }
8582
8583 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008584
8585BYPASS_AU:
8586 /* When wiping out a buffer make sure all its buffer-local autocommands
8587 * are deleted. */
8588 if (event == EVENT_BUFWIPEOUT && buf != NULL)
8589 aubuflocal_remove(buf);
8590
Bram Moolenaar071d4272004-06-13 20:20:40 +00008591 return retval;
8592}
8593
8594/*
8595 * Find next autocommand pattern that matches.
8596 */
8597 static void
8598auto_next_pat(apc, stop_at_last)
8599 AutoPatCmd *apc;
8600 int stop_at_last; /* stop when 'last' flag is set */
8601{
8602 AutoPat *ap;
8603 AutoCmd *cp;
8604 char_u *name;
8605 char *s;
8606
8607 vim_free(sourcing_name);
8608 sourcing_name = NULL;
8609
8610 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8611 {
8612 apc->curpat = NULL;
8613
8614 /* only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008615 * the group matches. For buffer-local autocommands only check the
8616 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008617 if (ap->pat != NULL && ap->cmds != NULL
8618 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8619 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008620 /* execution-condition */
8621 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008622 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
8623 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008624 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008625 {
8626 name = event_nr2name(apc->event);
8627 s = _("%s Auto commands for \"%s\"");
8628 sourcing_name = alloc((unsigned)(STRLEN(s)
8629 + STRLEN(name) + ap->patlen + 1));
8630 if (sourcing_name != NULL)
8631 {
8632 sprintf((char *)sourcing_name, s,
8633 (char *)name, (char *)ap->pat);
8634 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008635 {
8636 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008637 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008638 verbose_leave();
8639 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008640 }
8641
8642 apc->curpat = ap;
8643 apc->nextcmd = ap->cmds;
8644 /* mark last command */
8645 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8646 cp->last = FALSE;
8647 cp->last = TRUE;
8648 }
8649 line_breakcheck();
8650 if (apc->curpat != NULL) /* found a match */
8651 break;
8652 }
8653 if (stop_at_last && ap->last)
8654 break;
8655 }
8656}
8657
8658/*
8659 * Get next autocommand command.
8660 * Called by do_cmdline() to get the next line for ":if".
8661 * Returns allocated string, or NULL for end of autocommands.
8662 */
8663/* ARGSUSED */
8664 static char_u *
8665getnextac(c, cookie, indent)
8666 int c; /* not used */
8667 void *cookie;
8668 int indent; /* not used */
8669{
8670 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8671 char_u *retval;
8672 AutoCmd *ac;
8673
8674 /* Can be called again after returning the last line. */
8675 if (acp->curpat == NULL)
8676 return NULL;
8677
8678 /* repeat until we find an autocommand to execute */
8679 for (;;)
8680 {
8681 /* skip removed commands */
8682 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8683 if (acp->nextcmd->last)
8684 acp->nextcmd = NULL;
8685 else
8686 acp->nextcmd = acp->nextcmd->next;
8687
8688 if (acp->nextcmd != NULL)
8689 break;
8690
8691 /* at end of commands, find next pattern that matches */
8692 if (acp->curpat->last)
8693 acp->curpat = NULL;
8694 else
8695 acp->curpat = acp->curpat->next;
8696 if (acp->curpat != NULL)
8697 auto_next_pat(acp, TRUE);
8698 if (acp->curpat == NULL)
8699 return NULL;
8700 }
8701
8702 ac = acp->nextcmd;
8703
8704 if (p_verbose >= 9)
8705 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008706 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008707 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008708 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008709 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008710 }
8711 retval = vim_strsave(ac->cmd);
8712 autocmd_nested = ac->nested;
8713#ifdef FEAT_EVAL
8714 current_SID = ac->scriptID;
8715#endif
8716 if (ac->last)
8717 acp->nextcmd = NULL;
8718 else
8719 acp->nextcmd = ac->next;
8720 return retval;
8721}
8722
8723/*
8724 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008725 * To account for buffer-local autocommands, function needs to know
8726 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008727 */
8728 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008729has_autocmd(event, sfname, buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008730 EVENT_T event;
8731 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008732 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008733{
8734 AutoPat *ap;
8735 char_u *fname;
8736 char_u *tail = gettail(sfname);
8737 int retval = FALSE;
8738
8739 fname = FullName_save(sfname, FALSE);
8740 if (fname == NULL)
8741 return FALSE;
8742
8743#ifdef BACKSLASH_IN_FILENAME
8744 /*
8745 * Replace all backslashes with forward slashes. This makes the
8746 * autocommand patterns portable between Unix and MS-DOS.
8747 */
8748 sfname = vim_strsave(sfname);
8749 if (sfname != NULL)
8750 forward_slash(sfname);
8751 forward_slash(fname);
8752#endif
8753
8754 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8755 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008756 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008757 ? match_file_pat(NULL, ap->reg_prog,
8758 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008759 : buf != NULL && ap->buflocal_nr == buf->b_fnum
8760 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008761 {
8762 retval = TRUE;
8763 break;
8764 }
8765
8766 vim_free(fname);
8767#ifdef BACKSLASH_IN_FILENAME
8768 vim_free(sfname);
8769#endif
8770
8771 return retval;
8772}
8773
8774#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8775/*
8776 * Function given to ExpandGeneric() to obtain the list of autocommand group
8777 * names.
8778 */
8779/*ARGSUSED*/
8780 char_u *
8781get_augroup_name(xp, idx)
8782 expand_T *xp;
8783 int idx;
8784{
8785 if (idx == augroups.ga_len) /* add "END" add the end */
8786 return (char_u *)"END";
8787 if (idx >= augroups.ga_len) /* end of list */
8788 return NULL;
8789 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8790 return (char_u *)"";
8791 return AUGROUP_NAME(idx); /* return a name */
8792}
8793
8794static int include_groups = FALSE;
8795
8796 char_u *
8797set_context_in_autocmd(xp, arg, doautocmd)
8798 expand_T *xp;
8799 char_u *arg;
8800 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8801{
8802 char_u *p;
8803 int group;
8804
8805 /* check for a group name, skip it if present */
8806 include_groups = FALSE;
8807 p = arg;
8808 group = au_get_grouparg(&arg);
8809 if (group == AUGROUP_ERROR)
8810 return NULL;
8811 /* If there only is a group name that's what we expand. */
8812 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8813 {
8814 arg = p;
8815 group = AUGROUP_ALL;
8816 }
8817
8818 /* skip over event name */
8819 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8820 if (*p == ',')
8821 arg = p + 1;
8822 if (*p == NUL)
8823 {
8824 if (group == AUGROUP_ALL)
8825 include_groups = TRUE;
8826 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8827 xp->xp_pattern = arg;
8828 return NULL;
8829 }
8830
8831 /* skip over pattern */
8832 arg = skipwhite(p);
8833 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8834 arg++;
8835 if (*arg)
8836 return arg; /* expand (next) command */
8837
8838 if (doautocmd)
8839 xp->xp_context = EXPAND_FILES; /* expand file names */
8840 else
8841 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8842 return NULL;
8843}
8844
8845/*
8846 * Function given to ExpandGeneric() to obtain the list of event names.
8847 */
8848/*ARGSUSED*/
8849 char_u *
8850get_event_name(xp, idx)
8851 expand_T *xp;
8852 int idx;
8853{
8854 if (idx < augroups.ga_len) /* First list group names, if wanted */
8855 {
8856 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8857 return (char_u *)""; /* skip deleted entries */
8858 return AUGROUP_NAME(idx); /* return a name */
8859 }
8860 return (char_u *)event_names[idx - augroups.ga_len].name;
8861}
8862
8863#endif /* FEAT_CMDL_COMPL */
8864
8865/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008866 * Return TRUE if autocmd is supported.
8867 */
8868 int
8869autocmd_supported(name)
8870 char_u *name;
8871{
8872 char_u *p;
8873
8874 return (event_name2nr(name, &p) != NUM_EVENTS);
8875}
8876
8877/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00008878 * Return TRUE if an autocommand is defined for a group, event and
8879 * pattern: The group can be omitted to accept any group. "event" and "pattern"
8880 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
8881 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
8882 * Used for:
8883 * exists("#Group") or
8884 * exists("#Group#Event") or
8885 * exists("#Group#Event#pat") or
8886 * exists("#Event") or
8887 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00008888 */
8889 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00008890au_exists(arg)
8891 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008892{
Bram Moolenaar195d6352005-12-19 22:08:24 +00008893 char_u *arg_save;
8894 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008895 char_u *event_name;
8896 char_u *p;
8897 EVENT_T event;
8898 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008899 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00008900 int group;
8901 int retval = FALSE;
8902
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008903 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00008904 arg_save = vim_strsave(arg);
8905 if (arg_save == NULL)
8906 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008907 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00008908 if (p != NULL)
8909 *p++ = NUL;
8910
8911 /* First, look for an autocmd group name */
8912 group = au_find_group(arg_save);
8913 if (group == AUGROUP_ERROR)
8914 {
8915 /* Didn't match a group name, assume the first argument is an event. */
8916 group = AUGROUP_ALL;
8917 event_name = arg_save;
8918 }
8919 else
8920 {
8921 if (p == NULL)
8922 {
8923 /* "Group": group name is present and it's recognized */
8924 retval = TRUE;
8925 goto theend;
8926 }
8927
8928 /* Must be "Group#Event" or "Group#Event#pat". */
8929 event_name = p;
8930 p = vim_strchr(event_name, '#');
8931 if (p != NULL)
8932 *p++ = NUL; /* "Group#Event#pat" */
8933 }
8934
8935 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008936
8937 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008938 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008939
8940 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00008941 if (event == NUM_EVENTS)
8942 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943
8944 /* Find the first autocommand for this event.
8945 * If there isn't any, return FALSE;
8946 * If there is one and no pattern given, return TRUE; */
8947 ap = first_autopat[(int)event];
8948 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00008949 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008950 if (pattern == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00008951 {
8952 retval = TRUE;
8953 goto theend;
8954 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008955
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008956 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
8957 /* for pattern "<buffer=N>, fnamecmp() will work fine */
8958 if (STRICMP(pattern, "<buffer>") == 0)
8959 buflocal_buf = curbuf;
8960
Bram Moolenaar071d4272004-06-13 20:20:40 +00008961 /* Check if there is an autocommand with the given pattern. */
8962 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008963 /* only use a pattern when it has not been removed and has commands. */
8964 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008965 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00008966 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008967 && (buflocal_buf == NULL
8968 ? fnamecmp(ap->pat, pattern) == 0
8969 : ap->buflocal_nr == buflocal_buf->b_fnum))
Bram Moolenaar195d6352005-12-19 22:08:24 +00008970 {
8971 retval = TRUE;
8972 break;
8973 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008974
Bram Moolenaar195d6352005-12-19 22:08:24 +00008975theend:
8976 vim_free(arg_save);
8977 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008978}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008979
Bram Moolenaar071d4272004-06-13 20:20:40 +00008980#endif /* FEAT_AUTOCMD */
8981
8982#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
8983/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00008984 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
8985 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
8986 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008987 * Used for autocommands and 'wildignore'.
8988 * Returns TRUE if there is a match, FALSE otherwise.
8989 */
8990 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00008991match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008992 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00008993 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008994 char_u *fname; /* full path of file name */
8995 char_u *sfname; /* short file name or NULL */
8996 char_u *tail; /* tail of path */
8997 int allow_dirs; /* allow matching with dir */
8998{
8999 regmatch_T regmatch;
9000 int result = FALSE;
9001#ifdef FEAT_OSFILETYPE
9002 int no_pattern = FALSE; /* TRUE if check is filetype only */
9003 char_u *type_start;
9004 char_u c;
9005 int match = FALSE;
9006#endif
9007
9008#ifdef CASE_INSENSITIVE_FILENAME
9009 regmatch.rm_ic = TRUE; /* Always ignore case */
9010#else
9011 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
9012#endif
9013#ifdef FEAT_OSFILETYPE
9014 if (*pattern == '<')
9015 {
9016 /* There is a filetype condition specified with this pattern.
9017 * Check the filetype matches first. If not, don't bother with the
9018 * pattern (set regprog to NULL).
9019 * Always use magic for the regexp.
9020 */
9021
9022 for (type_start = pattern + 1; (c = *pattern); pattern++)
9023 {
9024 if ((c == ';' || c == '>') && match == FALSE)
9025 {
9026 *pattern = NUL; /* Terminate the string */
9027 match = mch_check_filetype(fname, type_start);
9028 *pattern = c; /* Restore the terminator */
9029 type_start = pattern + 1;
9030 }
9031 if (c == '>')
9032 break;
9033 }
9034
9035 /* (c should never be NUL, but check anyway) */
9036 if (match == FALSE || c == NUL)
9037 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
9038 else if (*pattern == NUL)
9039 {
9040 regmatch.regprog = NULL; /* Vim will try to free regprog later */
9041 no_pattern = TRUE; /* Always matches - don't check pat. */
9042 }
9043 else
9044 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
9045 }
9046 else
9047#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00009048 {
9049 if (prog != NULL)
9050 regmatch.regprog = prog;
9051 else
9052 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
9053 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009054
9055 /*
9056 * Try for a match with the pattern with:
9057 * 1. the full file name, when the pattern has a '/'.
9058 * 2. the short file name, when the pattern has a '/'.
9059 * 3. the tail of the file name, when the pattern has no '/'.
9060 */
9061 if (
9062#ifdef FEAT_OSFILETYPE
9063 /* If the check is for a filetype only and we don't care
9064 * about the path then skip all the regexp stuff.
9065 */
9066 no_pattern ||
9067#endif
9068 (regmatch.regprog != NULL
9069 && ((allow_dirs
9070 && (vim_regexec(&regmatch, fname, (colnr_T)0)
9071 || (sfname != NULL
9072 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
9073 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
9074 result = TRUE;
9075
Bram Moolenaar748bf032005-02-02 23:04:36 +00009076 if (prog == NULL)
9077 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009078 return result;
9079}
9080#endif
9081
9082#if defined(FEAT_WILDIGN) || defined(PROTO)
9083/*
9084 * Return TRUE if a file matches with a pattern in "list".
9085 * "list" is a comma-separated list of patterns, like 'wildignore'.
9086 * "sfname" is the short file name or NULL, "ffname" the long file name.
9087 */
9088 int
9089match_file_list(list, sfname, ffname)
9090 char_u *list;
9091 char_u *sfname;
9092 char_u *ffname;
9093{
9094 char_u buf[100];
9095 char_u *tail;
9096 char_u *regpat;
9097 char allow_dirs;
9098 int match;
9099 char_u *p;
9100
9101 tail = gettail(sfname);
9102
9103 /* try all patterns in 'wildignore' */
9104 p = list;
9105 while (*p)
9106 {
9107 copy_option_part(&p, buf, 100, ",");
9108 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
9109 if (regpat == NULL)
9110 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00009111 match = match_file_pat(regpat, NULL, ffname, sfname,
9112 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009113 vim_free(regpat);
9114 if (match)
9115 return TRUE;
9116 }
9117 return FALSE;
9118}
9119#endif
9120
9121/*
9122 * Convert the given pattern "pat" which has shell style wildcards in it, into
9123 * a regular expression, and return the result in allocated memory. If there
9124 * is a directory path separator to be matched, then TRUE is put in
9125 * allow_dirs, otherwise FALSE is put there -- webb.
9126 * Handle backslashes before special characters, like "\*" and "\ ".
9127 *
9128 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
9129 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
9130 *
9131 * Returns NULL when out of memory.
9132 */
9133/*ARGSUSED*/
9134 char_u *
9135file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
9136 char_u *pat;
9137 char_u *pat_end; /* first char after pattern or NULL */
9138 char *allow_dirs; /* Result passed back out in here */
9139 int no_bslash; /* Don't use a backward slash as pathsep */
9140{
9141 int size;
9142 char_u *endp;
9143 char_u *reg_pat;
9144 char_u *p;
9145 int i;
9146 int nested = 0;
9147 int add_dollar = TRUE;
9148#ifdef FEAT_OSFILETYPE
9149 int check_length = 0;
9150#endif
9151
9152 if (allow_dirs != NULL)
9153 *allow_dirs = FALSE;
9154 if (pat_end == NULL)
9155 pat_end = pat + STRLEN(pat);
9156
9157#ifdef FEAT_OSFILETYPE
9158 /* Find out how much of the string is the filetype check */
9159 if (*pat == '<')
9160 {
9161 /* Count chars until the next '>' */
9162 for (p = pat + 1; p < pat_end && *p != '>'; p++)
9163 ;
9164 if (p < pat_end)
9165 {
9166 /* Pattern is of the form <.*>.* */
9167 check_length = p - pat + 1;
9168 if (p + 1 >= pat_end)
9169 {
9170 /* The 'pattern' is a filetype check ONLY */
9171 reg_pat = (char_u *)alloc(check_length + 1);
9172 if (reg_pat != NULL)
9173 {
9174 mch_memmove(reg_pat, pat, (size_t)check_length);
9175 reg_pat[check_length] = NUL;
9176 }
9177 return reg_pat;
9178 }
9179 }
9180 /* else: there was no closing '>' - assume it was a normal pattern */
9181
9182 }
9183 pat += check_length;
9184 size = 2 + check_length;
9185#else
9186 size = 2; /* '^' at start, '$' at end */
9187#endif
9188
9189 for (p = pat; p < pat_end; p++)
9190 {
9191 switch (*p)
9192 {
9193 case '*':
9194 case '.':
9195 case ',':
9196 case '{':
9197 case '}':
9198 case '~':
9199 size += 2; /* extra backslash */
9200 break;
9201#ifdef BACKSLASH_IN_FILENAME
9202 case '\\':
9203 case '/':
9204 size += 4; /* could become "[\/]" */
9205 break;
9206#endif
9207 default:
9208 size++;
9209# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009210 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009211 {
9212 ++p;
9213 ++size;
9214 }
9215# endif
9216 break;
9217 }
9218 }
9219 reg_pat = alloc(size + 1);
9220 if (reg_pat == NULL)
9221 return NULL;
9222
9223#ifdef FEAT_OSFILETYPE
9224 /* Copy the type check in to the start. */
9225 if (check_length)
9226 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
9227 i = check_length;
9228#else
9229 i = 0;
9230#endif
9231
9232 if (pat[0] == '*')
9233 while (pat[0] == '*' && pat < pat_end - 1)
9234 pat++;
9235 else
9236 reg_pat[i++] = '^';
9237 endp = pat_end - 1;
9238 if (*endp == '*')
9239 {
9240 while (endp - pat > 0 && *endp == '*')
9241 endp--;
9242 add_dollar = FALSE;
9243 }
9244 for (p = pat; *p && nested >= 0 && p <= endp; p++)
9245 {
9246 switch (*p)
9247 {
9248 case '*':
9249 reg_pat[i++] = '.';
9250 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +00009251 while (p[1] == '*') /* "**" matches like "*" */
9252 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009253 break;
9254 case '.':
9255#ifdef RISCOS
9256 if (allow_dirs != NULL)
9257 *allow_dirs = TRUE;
9258 /* FALLTHROUGH */
9259#endif
9260 case '~':
9261 reg_pat[i++] = '\\';
9262 reg_pat[i++] = *p;
9263 break;
9264 case '?':
9265#ifdef RISCOS
9266 case '#':
9267#endif
9268 reg_pat[i++] = '.';
9269 break;
9270 case '\\':
9271 if (p[1] == NUL)
9272 break;
9273#ifdef BACKSLASH_IN_FILENAME
9274 if (!no_bslash)
9275 {
9276 /* translate:
9277 * "\x" to "\\x" e.g., "dir\file"
9278 * "\*" to "\\.*" e.g., "dir\*.c"
9279 * "\?" to "\\." e.g., "dir\??.c"
9280 * "\+" to "\+" e.g., "fileX\+.c"
9281 */
9282 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
9283 && p[1] != '+')
9284 {
9285 reg_pat[i++] = '[';
9286 reg_pat[i++] = '\\';
9287 reg_pat[i++] = '/';
9288 reg_pat[i++] = ']';
9289 if (allow_dirs != NULL)
9290 *allow_dirs = TRUE;
9291 break;
9292 }
9293 }
9294#endif
9295 if (*++p == '?'
9296#ifdef BACKSLASH_IN_FILENAME
9297 && no_bslash
9298#endif
9299 )
9300 reg_pat[i++] = '?';
9301 else
9302 if (*p == ',')
9303 reg_pat[i++] = ',';
9304 else
9305 {
9306 if (allow_dirs != NULL && vim_ispathsep(*p)
9307#ifdef BACKSLASH_IN_FILENAME
9308 && (!no_bslash || *p != '\\')
9309#endif
9310 )
9311 *allow_dirs = TRUE;
9312 reg_pat[i++] = '\\';
9313 reg_pat[i++] = *p;
9314 }
9315 break;
9316#ifdef BACKSLASH_IN_FILENAME
9317 case '/':
9318 reg_pat[i++] = '[';
9319 reg_pat[i++] = '\\';
9320 reg_pat[i++] = '/';
9321 reg_pat[i++] = ']';
9322 if (allow_dirs != NULL)
9323 *allow_dirs = TRUE;
9324 break;
9325#endif
9326 case '{':
9327 reg_pat[i++] = '\\';
9328 reg_pat[i++] = '(';
9329 nested++;
9330 break;
9331 case '}':
9332 reg_pat[i++] = '\\';
9333 reg_pat[i++] = ')';
9334 --nested;
9335 break;
9336 case ',':
9337 if (nested)
9338 {
9339 reg_pat[i++] = '\\';
9340 reg_pat[i++] = '|';
9341 }
9342 else
9343 reg_pat[i++] = ',';
9344 break;
9345 default:
9346# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009347 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009348 reg_pat[i++] = *p++;
9349 else
9350# endif
9351 if (allow_dirs != NULL && vim_ispathsep(*p))
9352 *allow_dirs = TRUE;
9353 reg_pat[i++] = *p;
9354 break;
9355 }
9356 }
9357 if (add_dollar)
9358 reg_pat[i++] = '$';
9359 reg_pat[i] = NUL;
9360 if (nested != 0)
9361 {
9362 if (nested < 0)
9363 EMSG(_("E219: Missing {."));
9364 else
9365 EMSG(_("E220: Missing }."));
9366 vim_free(reg_pat);
9367 reg_pat = NULL;
9368 }
9369 return reg_pat;
9370}