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