blob: 302e93a5174cd140d6c2dcb6e4dbb856f8405bc0 [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
Bram Moolenaar98358622005-11-28 22:58:23 +00003153 /* Close the file before removing it, on MS-Windows we
3154 * can't delete an open file. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003155 close(fd);
Bram Moolenaar98358622005-11-28 22:58:23 +00003156 mch_remove(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003157 }
3158 }
3159 }
3160
3161# ifdef UNIX
3162 /*
3163 * Break symlinks and/or hardlinks if we've been asked to.
3164 */
3165 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3166 {
3167 int lstat_res;
3168
3169 lstat_res = mch_lstat((char *)fname, &st);
3170
3171 /* Symlinks. */
3172 if ((bkc_flags & BKC_BREAKSYMLINK)
3173 && lstat_res == 0
3174 && st.st_ino != st_old.st_ino)
3175 backup_copy = FALSE;
3176
3177 /* Hardlinks. */
3178 if ((bkc_flags & BKC_BREAKHARDLINK)
3179 && st_old.st_nlink > 1
3180 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3181 backup_copy = FALSE;
3182 }
3183#endif
3184
3185#endif
3186
3187 /* make sure we have a valid backup extension to use */
3188 if (*p_bex == NUL)
3189 {
3190#ifdef RISCOS
3191 backup_ext = (char_u *)"/bak";
3192#else
3193 backup_ext = (char_u *)".bak";
3194#endif
3195 }
3196 else
3197 backup_ext = p_bex;
3198
3199 if (backup_copy
3200 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3201 {
3202 int bfd;
3203 char_u *copybuf, *wp;
3204 int some_error = FALSE;
3205 struct stat st_new;
3206 char_u *dirp;
3207 char_u *rootname;
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003208#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209 int did_set_shortname;
3210#endif
3211
3212 copybuf = alloc(BUFSIZE + 1);
3213 if (copybuf == NULL)
3214 {
3215 some_error = TRUE; /* out of memory */
3216 goto nobackup;
3217 }
3218
3219 /*
3220 * Try to make the backup in each directory in the 'bdir' option.
3221 *
3222 * Unix semantics has it, that we may have a writable file,
3223 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3224 * - the directory is not writable,
3225 * - the file may be a symbolic link,
3226 * - the file may belong to another user/group, etc.
3227 *
3228 * For these reasons, the existing writable file must be truncated
3229 * and reused. Creation of a backup COPY will be attempted.
3230 */
3231 dirp = p_bdir;
3232 while (*dirp)
3233 {
3234#ifdef UNIX
3235 st_new.st_ino = 0;
3236 st_new.st_dev = 0;
3237 st_new.st_gid = 0;
3238#endif
3239
3240 /*
3241 * Isolate one directory name, using an entry in 'bdir'.
3242 */
3243 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3244 rootname = get_file_in_dir(fname, copybuf);
3245 if (rootname == NULL)
3246 {
3247 some_error = TRUE; /* out of memory */
3248 goto nobackup;
3249 }
3250
Bram Moolenaard857f0e2005-06-21 22:37:39 +00003251#if defined(UNIX) && !defined(SHORT_FNAME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003252 did_set_shortname = FALSE;
3253#endif
3254
3255 /*
3256 * May try twice if 'shortname' not set.
3257 */
3258 for (;;)
3259 {
3260 /*
3261 * Make backup file name.
3262 */
3263 backup = buf_modname(
3264#ifdef SHORT_FNAME
3265 TRUE,
3266#else
3267 (buf->b_p_sn || buf->b_shortname),
3268#endif
3269 rootname, backup_ext, FALSE);
3270 if (backup == NULL)
3271 {
3272 vim_free(rootname);
3273 some_error = TRUE; /* out of memory */
3274 goto nobackup;
3275 }
3276
3277 /*
3278 * Check if backup file already exists.
3279 */
3280 if (mch_stat((char *)backup, &st_new) >= 0)
3281 {
3282#ifdef UNIX
3283 /*
3284 * Check if backup file is same as original file.
3285 * May happen when modname() gave the same file back.
3286 * E.g. silly link, or file name-length reached.
3287 * If we don't check here, we either ruin the file
3288 * when copying or erase it after writing. jw.
3289 */
3290 if (st_new.st_dev == st_old.st_dev
3291 && st_new.st_ino == st_old.st_ino)
3292 {
3293 vim_free(backup);
3294 backup = NULL; /* no backup file to delete */
3295# ifndef SHORT_FNAME
3296 /*
3297 * may try again with 'shortname' set
3298 */
3299 if (!(buf->b_shortname || buf->b_p_sn))
3300 {
3301 buf->b_shortname = TRUE;
3302 did_set_shortname = TRUE;
3303 continue;
3304 }
3305 /* setting shortname didn't help */
3306 if (did_set_shortname)
3307 buf->b_shortname = FALSE;
3308# endif
3309 break;
3310 }
3311#endif
3312
3313 /*
3314 * If we are not going to keep the backup file, don't
3315 * delete an existing one, try to use another name.
3316 * Change one character, just before the extension.
3317 */
3318 if (!p_bk)
3319 {
3320 wp = backup + STRLEN(backup) - 1
3321 - STRLEN(backup_ext);
3322 if (wp < backup) /* empty file name ??? */
3323 wp = backup;
3324 *wp = 'z';
3325 while (*wp > 'a'
3326 && mch_stat((char *)backup, &st_new) >= 0)
3327 --*wp;
3328 /* They all exist??? Must be something wrong. */
3329 if (*wp == 'a')
3330 {
3331 vim_free(backup);
3332 backup = NULL;
3333 }
3334 }
3335 }
3336 break;
3337 }
3338 vim_free(rootname);
3339
3340 /*
3341 * Try to create the backup file
3342 */
3343 if (backup != NULL)
3344 {
3345 /* remove old backup, if present */
3346 mch_remove(backup);
3347 /* Open with O_EXCL to avoid the file being created while
3348 * we were sleeping (symlink hacker attack?) */
3349 bfd = mch_open((char *)backup,
Bram Moolenaara5792f52005-11-23 21:25:05 +00003350 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW,
3351 perm & 0777);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003352 if (bfd < 0)
3353 {
3354 vim_free(backup);
3355 backup = NULL;
3356 }
3357 else
3358 {
3359 /* set file protection same as original file, but
3360 * strip s-bit */
3361 (void)mch_setperm(backup, perm & 0777);
3362
3363#ifdef UNIX
3364 /*
3365 * Try to set the group of the backup same as the
3366 * original file. If this fails, set the protection
3367 * bits for the group same as the protection bits for
3368 * others.
3369 */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003370 if (st_new.st_gid != st_old.st_gid
Bram Moolenaar071d4272004-06-13 20:20:40 +00003371# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
Bram Moolenaara5792f52005-11-23 21:25:05 +00003372 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003373# endif
3374 )
3375 mch_setperm(backup,
3376 (perm & 0707) | ((perm & 07) << 3));
3377#endif
3378
3379 /*
3380 * copy the file.
3381 */
3382 write_info.bw_fd = bfd;
3383 write_info.bw_buf = copybuf;
3384#ifdef HAS_BW_FLAGS
3385 write_info.bw_flags = FIO_NOCONVERT;
3386#endif
3387 while ((write_info.bw_len = vim_read(fd, copybuf,
3388 BUFSIZE)) > 0)
3389 {
3390 if (buf_write_bytes(&write_info) == FAIL)
3391 {
3392 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3393 break;
3394 }
3395 ui_breakcheck();
3396 if (got_int)
3397 {
3398 errmsg = (char_u *)_(e_interr);
3399 break;
3400 }
3401 }
3402
3403 if (close(bfd) < 0 && errmsg == NULL)
3404 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3405 if (write_info.bw_len < 0)
3406 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3407#ifdef UNIX
3408 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3409#endif
3410#ifdef HAVE_ACL
3411 mch_set_acl(backup, acl);
3412#endif
3413 break;
3414 }
3415 }
3416 }
3417 nobackup:
3418 close(fd); /* ignore errors for closing read file */
3419 vim_free(copybuf);
3420
3421 if (backup == NULL && errmsg == NULL)
3422 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3423 /* ignore errors when forceit is TRUE */
3424 if ((some_error || errmsg != NULL) && !forceit)
3425 {
3426 retval = FAIL;
3427 goto fail;
3428 }
3429 errmsg = NULL;
3430 }
3431 else
3432 {
3433 char_u *dirp;
3434 char_u *p;
3435 char_u *rootname;
3436
3437 /*
3438 * Make a backup by renaming the original file.
3439 */
3440 /*
3441 * If 'cpoptions' includes the "W" flag, we don't want to
3442 * overwrite a read-only file. But rename may be possible
3443 * anyway, thus we need an extra check here.
3444 */
3445 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3446 {
3447 errnum = (char_u *)"E504: ";
3448 errmsg = (char_u *)_(err_readonly);
3449 goto fail;
3450 }
3451
3452 /*
3453 *
3454 * Form the backup file name - change path/fo.o.h to
3455 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3456 * that works is used.
3457 */
3458 dirp = p_bdir;
3459 while (*dirp)
3460 {
3461 /*
3462 * Isolate one directory name and make the backup file name.
3463 */
3464 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3465 rootname = get_file_in_dir(fname, IObuff);
3466 if (rootname == NULL)
3467 backup = NULL;
3468 else
3469 {
3470 backup = buf_modname(
3471#ifdef SHORT_FNAME
3472 TRUE,
3473#else
3474 (buf->b_p_sn || buf->b_shortname),
3475#endif
3476 rootname, backup_ext, FALSE);
3477 vim_free(rootname);
3478 }
3479
3480 if (backup != NULL)
3481 {
3482 /*
3483 * If we are not going to keep the backup file, don't
3484 * delete an existing one, try to use another name.
3485 * Change one character, just before the extension.
3486 */
3487 if (!p_bk && mch_getperm(backup) >= 0)
3488 {
3489 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3490 if (p < backup) /* empty file name ??? */
3491 p = backup;
3492 *p = 'z';
3493 while (*p > 'a' && mch_getperm(backup) >= 0)
3494 --*p;
3495 /* They all exist??? Must be something wrong! */
3496 if (*p == 'a')
3497 {
3498 vim_free(backup);
3499 backup = NULL;
3500 }
3501 }
3502 }
3503 if (backup != NULL)
3504 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003505 /*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00003506 * Delete any existing backup and move the current version
3507 * to the backup. For safety, we don't remove the backup
3508 * until the write has finished successfully. And if the
3509 * 'backup' option is set, leave it around.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003510 */
3511 /*
3512 * If the renaming of the original file to the backup file
3513 * works, quit here.
3514 */
3515 if (vim_rename(fname, backup) == 0)
3516 break;
3517
3518 vim_free(backup); /* don't do the rename below */
3519 backup = NULL;
3520 }
3521 }
3522 if (backup == NULL && !forceit)
3523 {
3524 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3525 goto fail;
3526 }
3527 }
3528 }
3529
3530#if defined(UNIX) && !defined(ARCHIE)
3531 /* When using ":w!" and the file was read-only: make it writable */
3532 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3533 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3534 {
3535 perm |= 0200;
3536 (void)mch_setperm(fname, perm);
3537 made_writable = TRUE;
3538 }
3539#endif
3540
3541 /* When using ":w!" and writing to the current file, readonly makes no
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003542 * sense, reset it, unless 'Z' appears in 'cpoptions'. */
3543 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003544 {
3545 buf->b_p_ro = FALSE;
3546#ifdef FEAT_TITLE
3547 need_maketitle = TRUE; /* set window title later */
3548#endif
3549#ifdef FEAT_WINDOWS
3550 status_redraw_all(); /* redraw status lines later */
3551#endif
3552 }
3553
3554 if (end > buf->b_ml.ml_line_count)
3555 end = buf->b_ml.ml_line_count;
3556 if (buf->b_ml.ml_flags & ML_EMPTY)
3557 start = end + 1;
3558
3559 /*
3560 * If the original file is being overwritten, there is a small chance that
3561 * we crash in the middle of writing. Therefore the file is preserved now.
3562 * This makes all block numbers positive so that recovery does not need
3563 * the original file.
3564 * Don't do this if there is a backup file and we are exiting.
3565 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003566 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00003567 && !(exiting && backup != NULL))
3568 {
3569 ml_preserve(buf, FALSE);
3570 if (got_int)
3571 {
3572 errmsg = (char_u *)_(e_interr);
3573 goto restore_backup;
3574 }
3575 }
3576
3577#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
3578 /*
3579 * Before risking to lose the original file verify if there's
3580 * a resource fork to preserve, and if cannot be done warn
3581 * the users. This happens when overwriting without backups.
3582 */
3583 if (backup == NULL && overwriting && !append)
3584 if (mch_has_resource_fork(fname))
3585 {
3586 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
3587 goto restore_backup;
3588 }
3589#endif
3590
3591#ifdef VMS
3592 vms_remove_version(fname); /* remove version */
3593#endif
3594 /* Default: write the the file directly. May write to a temp file for
3595 * multi-byte conversion. */
3596 wfname = fname;
3597
3598#ifdef FEAT_MBYTE
3599 /* Check for forced 'fileencoding' from "++opt=val" argument. */
3600 if (eap != NULL && eap->force_enc != 0)
3601 {
3602 fenc = eap->cmd + eap->force_enc;
3603 fenc = enc_canonize(fenc);
3604 fenc_tofree = fenc;
3605 }
3606 else
3607 fenc = buf->b_p_fenc;
3608
3609 /*
3610 * The file needs to be converted when 'fileencoding' is set and
3611 * 'fileencoding' differs from 'encoding'.
3612 */
3613 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
3614
3615 /*
3616 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3617 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3618 * Prepare the flags for it and allocate bw_conv_buf when needed.
3619 */
3620 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
3621 {
3622 wb_flags = get_fio_flags(fenc);
3623 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
3624 {
3625 /* Need to allocate a buffer to translate into. */
3626 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
3627 write_info.bw_conv_buflen = bufsize * 2;
3628 else /* FIO_UCS4 */
3629 write_info.bw_conv_buflen = bufsize * 4;
3630 write_info.bw_conv_buf
3631 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3632 if (write_info.bw_conv_buf == NULL)
3633 end = 0;
3634 }
3635 }
3636
3637# ifdef WIN3264
3638 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
3639 {
3640 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
3641 write_info.bw_conv_buflen = bufsize * 4;
3642 write_info.bw_conv_buf
3643 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3644 if (write_info.bw_conv_buf == NULL)
3645 end = 0;
3646 }
3647# endif
3648
3649# ifdef MACOS_X
3650 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
3651 {
3652 write_info.bw_conv_buflen = bufsize * 3;
3653 write_info.bw_conv_buf
3654 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3655 if (write_info.bw_conv_buf == NULL)
3656 end = 0;
3657 }
3658# endif
3659
3660# if defined(FEAT_EVAL) || defined(USE_ICONV)
3661 if (converted && wb_flags == 0)
3662 {
3663# ifdef USE_ICONV
3664 /*
3665 * Use iconv() conversion when conversion is needed and it's not done
3666 * internally.
3667 */
3668 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3669 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3670 if (write_info.bw_iconv_fd != (iconv_t)-1)
3671 {
3672 /* We're going to use iconv(), allocate a buffer to convert in. */
3673 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3674 write_info.bw_conv_buf
3675 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3676 if (write_info.bw_conv_buf == NULL)
3677 end = 0;
3678 write_info.bw_first = TRUE;
3679 }
3680# ifdef FEAT_EVAL
3681 else
3682# endif
3683# endif
3684
3685# ifdef FEAT_EVAL
3686 /*
3687 * When the file needs to be converted with 'charconvert' after
3688 * writing, write to a temp file instead and let the conversion
3689 * overwrite the original file.
3690 */
3691 if (*p_ccv != NUL)
3692 {
3693 wfname = vim_tempname('w');
3694 if (wfname == NULL) /* Can't write without a tempfile! */
3695 {
3696 errmsg = (char_u *)_("E214: Can't find temp file for writing");
3697 goto restore_backup;
3698 }
3699 }
3700# endif
3701 }
3702# endif
3703 if (converted && wb_flags == 0
3704# ifdef USE_ICONV
3705 && write_info.bw_iconv_fd == (iconv_t)-1
3706# endif
3707# ifdef FEAT_EVAL
3708 && wfname == fname
3709# endif
3710 )
3711 {
3712 if (!forceit)
3713 {
3714 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
3715 goto restore_backup;
3716 }
3717 notconverted = TRUE;
3718 }
3719#endif
3720
3721 /*
3722 * Open the file "wfname" for writing.
3723 * We may try to open the file twice: If we can't write to the
3724 * file and forceit is TRUE we delete the existing file and try to create
3725 * a new one. If this still fails we may have lost the original file!
3726 * (this may happen when the user reached his quotum for number of files).
3727 * Appending will fail if the file does not exist and forceit is FALSE.
3728 */
3729 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
3730 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3731 : (O_CREAT | O_TRUNC))
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00003732 , perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003733 {
3734 /*
3735 * A forced write will try to create a new file if the old one is
3736 * still readonly. This may also happen when the directory is
3737 * read-only. In that case the mch_remove() will fail.
3738 */
3739 if (errmsg == NULL)
3740 {
3741#ifdef UNIX
3742 struct stat st;
3743
3744 /* Don't delete the file when it's a hard or symbolic link. */
3745 if ((!newfile && st_old.st_nlink > 1)
3746 || (mch_lstat((char *)fname, &st) == 0
3747 && (st.st_dev != st_old.st_dev
3748 || st.st_ino != st_old.st_ino)))
3749 errmsg = (char_u *)_("E166: Can't open linked file for writing");
3750 else
3751#endif
3752 {
3753 errmsg = (char_u *)_("E212: Can't open file for writing");
3754 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
3755 && perm >= 0)
3756 {
3757#ifdef UNIX
3758 /* we write to the file, thus it should be marked
3759 writable after all */
3760 if (!(perm & 0200))
3761 made_writable = TRUE;
3762 perm |= 0200;
3763 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
3764 perm &= 0777;
3765#endif
3766 if (!append) /* don't remove when appending */
3767 mch_remove(wfname);
3768 continue;
3769 }
3770 }
3771 }
3772
3773restore_backup:
3774 {
3775 struct stat st;
3776
3777 /*
3778 * If we failed to open the file, we don't need a backup. Throw it
3779 * away. If we moved or removed the original file try to put the
3780 * backup in its place.
3781 */
3782 if (backup != NULL && wfname == fname)
3783 {
3784 if (backup_copy)
3785 {
3786 /*
3787 * There is a small chance that we removed the original,
3788 * try to move the copy in its place.
3789 * This may not work if the vim_rename() fails.
3790 * In that case we leave the copy around.
3791 */
3792 /* If file does not exist, put the copy in its place */
3793 if (mch_stat((char *)fname, &st) < 0)
3794 vim_rename(backup, fname);
3795 /* if original file does exist throw away the copy */
3796 if (mch_stat((char *)fname, &st) >= 0)
3797 mch_remove(backup);
3798 }
3799 else
3800 {
3801 /* try to put the original file back */
3802 vim_rename(backup, fname);
3803 }
3804 }
3805
3806 /* if original file no longer exists give an extra warning */
3807 if (!newfile && mch_stat((char *)fname, &st) < 0)
3808 end = 0;
3809 }
3810
3811#ifdef FEAT_MBYTE
3812 if (wfname != fname)
3813 vim_free(wfname);
3814#endif
3815 goto fail;
3816 }
3817 errmsg = NULL;
3818
3819#if defined(MACOS_CLASSIC) || defined(WIN3264)
3820 /* TODO: Is it need for MACOS_X? (Dany) */
3821 /*
3822 * On macintosh copy the original files attributes (i.e. the backup)
3823 * This is done in order to preserve the ressource fork and the
3824 * Finder attribute (label, comments, custom icons, file creatore)
3825 */
3826 if (backup != NULL && overwriting && !append)
3827 {
3828 if (backup_copy)
3829 (void)mch_copy_file_attribute(wfname, backup);
3830 else
3831 (void)mch_copy_file_attribute(backup, wfname);
3832 }
3833
3834 if (!overwriting && !append)
3835 {
3836 if (buf->b_ffname != NULL)
3837 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
3838 /* Should copy ressource fork */
3839 }
3840#endif
3841
3842 write_info.bw_fd = fd;
3843
3844#ifdef FEAT_CRYPT
3845 if (*buf->b_p_key && !filtering)
3846 {
3847 crypt_init_keys(buf->b_p_key);
3848 /* Write magic number, so that Vim knows that this file is encrypted
3849 * when reading it again. This also undergoes utf-8 to ucs-2/4
3850 * conversion when needed. */
3851 write_info.bw_buf = (char_u *)CRYPT_MAGIC;
3852 write_info.bw_len = CRYPT_MAGIC_LEN;
3853 write_info.bw_flags = FIO_NOCONVERT;
3854 if (buf_write_bytes(&write_info) == FAIL)
3855 end = 0;
3856 wb_flags |= FIO_ENCRYPTED;
3857 }
3858#endif
3859
3860 write_info.bw_buf = buffer;
3861 nchars = 0;
3862
3863 /* use "++bin", "++nobin" or 'binary' */
3864 if (eap != NULL && eap->force_bin != 0)
3865 write_bin = (eap->force_bin == FORCE_BIN);
3866 else
3867 write_bin = buf->b_p_bin;
3868
3869#ifdef FEAT_MBYTE
3870 /*
3871 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003872 * Skip it when appending and the file already existed, the BOM only makes
3873 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003874 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003875 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003876 {
3877 write_info.bw_len = make_bom(buffer, fenc);
3878 if (write_info.bw_len > 0)
3879 {
3880 /* don't convert, do encryption */
3881 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
3882 if (buf_write_bytes(&write_info) == FAIL)
3883 end = 0;
3884 else
3885 nchars += write_info.bw_len;
3886 }
3887 }
3888#endif
3889
3890 write_info.bw_len = bufsize;
3891#ifdef HAS_BW_FLAGS
3892 write_info.bw_flags = wb_flags;
3893#endif
3894 fileformat = get_fileformat_force(buf, eap);
3895 s = buffer;
3896 len = 0;
3897 for (lnum = start; lnum <= end; ++lnum)
3898 {
3899 /*
3900 * The next while loop is done once for each character written.
3901 * Keep it fast!
3902 */
3903 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
3904 while ((c = *++ptr) != NUL)
3905 {
3906 if (c == NL)
3907 *s = NUL; /* replace newlines with NULs */
3908 else if (c == CAR && fileformat == EOL_MAC)
3909 *s = NL; /* Mac: replace CRs with NLs */
3910 else
3911 *s = c;
3912 ++s;
3913 if (++len != bufsize)
3914 continue;
3915 if (buf_write_bytes(&write_info) == FAIL)
3916 {
3917 end = 0; /* write error: break loop */
3918 break;
3919 }
3920 nchars += bufsize;
3921 s = buffer;
3922 len = 0;
3923 }
3924 /* write failed or last line has no EOL: stop here */
3925 if (end == 0
3926 || (lnum == end
3927 && write_bin
3928 && (lnum == write_no_eol_lnum
3929 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
3930 {
3931 ++lnum; /* written the line, count it */
3932 no_eol = TRUE;
3933 break;
3934 }
3935 if (fileformat == EOL_UNIX)
3936 *s++ = NL;
3937 else
3938 {
3939 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
3940 if (fileformat == EOL_DOS) /* write CR-NL */
3941 {
3942 if (++len == bufsize)
3943 {
3944 if (buf_write_bytes(&write_info) == FAIL)
3945 {
3946 end = 0; /* write error: break loop */
3947 break;
3948 }
3949 nchars += bufsize;
3950 s = buffer;
3951 len = 0;
3952 }
3953 *s++ = NL;
3954 }
3955 }
3956 if (++len == bufsize && end)
3957 {
3958 if (buf_write_bytes(&write_info) == FAIL)
3959 {
3960 end = 0; /* write error: break loop */
3961 break;
3962 }
3963 nchars += bufsize;
3964 s = buffer;
3965 len = 0;
3966
3967 ui_breakcheck();
3968 if (got_int)
3969 {
3970 end = 0; /* Interrupted, break loop */
3971 break;
3972 }
3973 }
3974#ifdef VMS
3975 /*
3976 * On VMS there is a problem: newlines get added when writing blocks
3977 * at a time. Fix it by writing a line at a time.
3978 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003979 * Explanation: VAX/DECC RTL insists that records in some RMS
3980 * structures end with a newline (carriage return) character, and if
3981 * they don't it adds one.
3982 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003983 */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003984 if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003985 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003986 int b2write;
3987
3988 buf->b_fab_mrs = (buf->b_fab_mrs == 0
3989 ? MIN(4096, bufsize)
3990 : MIN(buf->b_fab_mrs, bufsize));
3991
3992 b2write = len;
3993 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003994 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003995 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
3996 if (buf_write_bytes(&write_info) == FAIL)
3997 {
3998 end = 0;
3999 break;
4000 }
4001 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004002 }
4003 write_info.bw_len = bufsize;
4004 nchars += len;
4005 s = buffer;
4006 len = 0;
4007 }
4008#endif
4009 }
4010 if (len > 0 && end > 0)
4011 {
4012 write_info.bw_len = len;
4013 if (buf_write_bytes(&write_info) == FAIL)
4014 end = 0; /* write error */
4015 nchars += len;
4016 }
4017
4018#if defined(UNIX) && defined(HAVE_FSYNC)
4019 /* On many journalling file systems there is a bug that causes both the
4020 * original and the backup file to be lost when halting the system right
4021 * after writing the file. That's because only the meta-data is
4022 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004023 * been written to disk and we don't lose it.
4024 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004025 * (could be a pipe).
4026 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
4027 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004028 {
4029 errmsg = (char_u *)_("E667: Fsync failed");
4030 end = 0;
4031 }
4032#endif
4033
Bram Moolenaara5792f52005-11-23 21:25:05 +00004034#ifdef UNIX
4035 /* When creating a new file, set its owner/group to that of the original
4036 * file. Get the new device and inode number. */
4037 if (backup != NULL && !backup_copy)
4038 {
4039# ifdef HAVE_FCHOWN
4040 struct stat st;
4041
4042 /* don't change the owner when it's already OK, some systems remove
4043 * permission or ACL stuff */
4044 if (mch_stat((char *)wfname, &st) < 0
4045 || st.st_uid != st_old.st_uid
4046 || st.st_gid != st_old.st_gid)
4047 {
4048 fchown(fd, st_old.st_uid, st_old.st_gid);
4049 if (perm >= 0) /* set permission again, may have changed */
4050 (void)mch_setperm(wfname, perm);
4051 }
4052# endif
4053 buf_setino(buf);
4054 }
4055#endif
4056
Bram Moolenaar071d4272004-06-13 20:20:40 +00004057 if (close(fd) != 0)
4058 {
4059 errmsg = (char_u *)_("E512: Close failed");
4060 end = 0;
4061 }
4062
4063#ifdef UNIX
4064 if (made_writable)
4065 perm &= ~0200; /* reset 'w' bit for security reasons */
4066#endif
4067 if (perm >= 0) /* set perm. of new file same as old file */
4068 (void)mch_setperm(wfname, perm);
4069#ifdef RISCOS
4070 if (!append && !filtering)
4071 /* Set the filetype after writing the file. */
4072 mch_set_filetype(wfname, buf->b_p_oft);
4073#endif
4074#ifdef HAVE_ACL
4075 /* Probably need to set the ACL before changing the user (can't set the
4076 * ACL on a file the user doesn't own). */
4077 if (!backup_copy)
4078 mch_set_acl(wfname, acl);
4079#endif
4080
Bram Moolenaar071d4272004-06-13 20:20:40 +00004081
4082#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4083 if (wfname != fname)
4084 {
4085 /*
4086 * The file was written to a temp file, now it needs to be converted
4087 * with 'charconvert' to (overwrite) the output file.
4088 */
4089 if (end != 0)
4090 {
4091 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4092 wfname, fname) == FAIL)
4093 {
4094 write_info.bw_conv_error = TRUE;
4095 end = 0;
4096 }
4097 }
4098 mch_remove(wfname);
4099 vim_free(wfname);
4100 }
4101#endif
4102
4103 if (end == 0)
4104 {
4105 if (errmsg == NULL)
4106 {
4107#ifdef FEAT_MBYTE
4108 if (write_info.bw_conv_error)
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00004109 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004110 else
4111#endif
4112 if (got_int)
4113 errmsg = (char_u *)_(e_interr);
4114 else
4115 errmsg = (char_u *)_("E514: write error (file system full?)");
4116 }
4117
4118 /*
4119 * If we have a backup file, try to put it in place of the new file,
4120 * because the new file is probably corrupt. This avoids loosing the
4121 * original file when trying to make a backup when writing the file a
4122 * second time.
4123 * When "backup_copy" is set we need to copy the backup over the new
4124 * file. Otherwise rename the backup file.
4125 * If this is OK, don't give the extra warning message.
4126 */
4127 if (backup != NULL)
4128 {
4129 if (backup_copy)
4130 {
4131 /* This may take a while, if we were interrupted let the user
4132 * know we got the message. */
4133 if (got_int)
4134 {
4135 MSG(_(e_interr));
4136 out_flush();
4137 }
4138 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4139 {
4140 if ((write_info.bw_fd = mch_open((char *)fname,
Bram Moolenaar9be038d2005-03-08 22:34:32 +00004141 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA,
4142 perm & 0777)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004143 {
4144 /* copy the file. */
4145 write_info.bw_buf = smallbuf;
4146#ifdef HAS_BW_FLAGS
4147 write_info.bw_flags = FIO_NOCONVERT;
4148#endif
4149 while ((write_info.bw_len = vim_read(fd, smallbuf,
4150 SMBUFSIZE)) > 0)
4151 if (buf_write_bytes(&write_info) == FAIL)
4152 break;
4153
4154 if (close(write_info.bw_fd) >= 0
4155 && write_info.bw_len == 0)
4156 end = 1; /* success */
4157 }
4158 close(fd); /* ignore errors for closing read file */
4159 }
4160 }
4161 else
4162 {
4163 if (vim_rename(backup, fname) == 0)
4164 end = 1;
4165 }
4166 }
4167 goto fail;
4168 }
4169
4170 lnum -= start; /* compute number of written lines */
4171 --no_wait_return; /* may wait for return now */
4172
4173#if !(defined(UNIX) || defined(VMS))
4174 fname = sfname; /* use shortname now, for the messages */
4175#endif
4176 if (!filtering)
4177 {
4178 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4179 c = FALSE;
4180#ifdef FEAT_MBYTE
4181 if (write_info.bw_conv_error)
4182 {
4183 STRCAT(IObuff, _(" CONVERSION ERROR"));
4184 c = TRUE;
4185 }
4186 else if (notconverted)
4187 {
4188 STRCAT(IObuff, _("[NOT converted]"));
4189 c = TRUE;
4190 }
4191 else if (converted)
4192 {
4193 STRCAT(IObuff, _("[converted]"));
4194 c = TRUE;
4195 }
4196#endif
4197 if (device)
4198 {
4199 STRCAT(IObuff, _("[Device]"));
4200 c = TRUE;
4201 }
4202 else if (newfile)
4203 {
4204 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4205 c = TRUE;
4206 }
4207 if (no_eol)
4208 {
4209 msg_add_eol();
4210 c = TRUE;
4211 }
4212 /* may add [unix/dos/mac] */
4213 if (msg_add_fileformat(fileformat))
4214 c = TRUE;
4215#ifdef FEAT_CRYPT
4216 if (wb_flags & FIO_ENCRYPTED)
4217 {
4218 STRCAT(IObuff, _("[crypted]"));
4219 c = TRUE;
4220 }
4221#endif
4222 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4223 if (!shortmess(SHM_WRITE))
4224 {
4225 if (append)
4226 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4227 else
4228 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4229 }
4230
4231 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
4232 keep_msg_attr = 0;
4233 }
4234
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004235 /* When written everything correctly: reset 'modified'. Unless not
4236 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004237 if (reset_changed && whole
4238#ifdef FEAT_MBYTE
4239 && !write_info.bw_conv_error
4240#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004241 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4242 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004243 {
4244 unchanged(buf, TRUE);
4245 u_unchanged(buf);
4246 }
4247
4248 /*
4249 * If written to the current file, update the timestamp of the swap file
4250 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4251 */
4252 if (overwriting)
4253 {
4254 ml_timestamp(buf);
4255 buf->b_flags &= ~BF_WRITE_MASK;
4256 }
4257
4258 /*
4259 * If we kept a backup until now, and we are in patch mode, then we make
4260 * the backup file our 'original' file.
4261 */
4262 if (*p_pm && dobackup)
4263 {
4264 char *org = (char *)buf_modname(
4265#ifdef SHORT_FNAME
4266 TRUE,
4267#else
4268 (buf->b_p_sn || buf->b_shortname),
4269#endif
4270 fname, p_pm, FALSE);
4271
4272 if (backup != NULL)
4273 {
4274 struct stat st;
4275
4276 /*
4277 * If the original file does not exist yet
4278 * the current backup file becomes the original file
4279 */
4280 if (org == NULL)
4281 EMSG(_("E205: Patchmode: can't save original file"));
4282 else if (mch_stat(org, &st) < 0)
4283 {
4284 vim_rename(backup, (char_u *)org);
4285 vim_free(backup); /* don't delete the file */
4286 backup = NULL;
4287#ifdef UNIX
4288 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4289#endif
4290 }
4291 }
4292 /*
4293 * If there is no backup file, remember that a (new) file was
4294 * created.
4295 */
4296 else
4297 {
4298 int empty_fd;
4299
4300 if (org == NULL
Bram Moolenaara5792f52005-11-23 21:25:05 +00004301 || (empty_fd = mch_open(org,
4302 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW,
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00004303 perm < 0 ? 0666 : (perm & 0777))) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004304 EMSG(_("E206: patchmode: can't touch empty original file"));
4305 else
4306 close(empty_fd);
4307 }
4308 if (org != NULL)
4309 {
4310 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4311 vim_free(org);
4312 }
4313 }
4314
4315 /*
4316 * Remove the backup unless 'backup' option is set
4317 */
4318 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4319 EMSG(_("E207: Can't delete backup file"));
4320
4321#ifdef FEAT_SUN_WORKSHOP
4322 if (usingSunWorkShop)
4323 workshop_file_saved((char *) ffname);
4324#endif
4325
4326 goto nofail;
4327
4328 /*
4329 * Finish up. We get here either after failure or success.
4330 */
4331fail:
4332 --no_wait_return; /* may wait for return now */
4333nofail:
4334
4335 /* Done saving, we accept changed buffer warnings again */
4336 buf->b_saving = FALSE;
4337
4338 vim_free(backup);
4339 if (buffer != smallbuf)
4340 vim_free(buffer);
4341#ifdef FEAT_MBYTE
4342 vim_free(fenc_tofree);
4343 vim_free(write_info.bw_conv_buf);
4344# ifdef USE_ICONV
4345 if (write_info.bw_iconv_fd != (iconv_t)-1)
4346 {
4347 iconv_close(write_info.bw_iconv_fd);
4348 write_info.bw_iconv_fd = (iconv_t)-1;
4349 }
4350# endif
4351#endif
4352#ifdef HAVE_ACL
4353 mch_free_acl(acl);
4354#endif
4355
4356 if (errmsg != NULL)
4357 {
4358 int numlen = errnum != NULL ? STRLEN(errnum) : 0;
4359
4360 attr = hl_attr(HLF_E); /* set highlight for error messages */
4361 msg_add_fname(buf,
4362#ifndef UNIX
4363 sfname
4364#else
4365 fname
4366#endif
4367 ); /* put file name in IObuff with quotes */
4368 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4369 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4370 /* If the error message has the form "is ...", put the error number in
4371 * front of the file name. */
4372 if (errnum != NULL)
4373 {
4374 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4375 mch_memmove(IObuff, errnum, (size_t)numlen);
4376 }
4377 STRCAT(IObuff, errmsg);
4378 emsg(IObuff);
4379
4380 retval = FAIL;
4381 if (end == 0)
4382 {
4383 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4384 attr | MSG_HIST);
4385 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4386 attr | MSG_HIST);
4387
4388 /* Update the timestamp to avoid an "overwrite changed file"
4389 * prompt when writing again. */
4390 if (mch_stat((char *)fname, &st_old) >= 0)
4391 {
4392 buf_store_time(buf, &st_old, fname);
4393 buf->b_mtime_read = buf->b_mtime;
4394 }
4395 }
4396 }
4397 msg_scroll = msg_save;
4398
4399#ifdef FEAT_AUTOCMD
4400#ifdef FEAT_EVAL
4401 if (!should_abort(retval))
4402#else
4403 if (!got_int)
4404#endif
4405 {
4406 aco_save_T aco;
4407
4408 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4409
4410 /*
4411 * Apply POST autocommands.
4412 * Careful: The autocommands may call buf_write() recursively!
4413 */
4414 aucmd_prepbuf(&aco, buf);
4415
4416 if (append)
4417 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4418 FALSE, curbuf, eap);
4419 else if (filtering)
4420 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4421 FALSE, curbuf, eap);
4422 else if (reset_changed && whole)
4423 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4424 FALSE, curbuf, eap);
4425 else
4426 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4427 FALSE, curbuf, eap);
4428
4429 /* restore curwin/curbuf and a few other things */
4430 aucmd_restbuf(&aco);
4431
4432#ifdef FEAT_EVAL
4433 if (aborting()) /* autocmds may abort script processing */
4434 retval = FALSE;
4435#endif
4436 }
4437#endif
4438
4439 got_int |= prev_got_int;
4440
4441#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4442 /* Update machine specific information. */
4443 mch_post_buffer_write(buf);
4444#endif
4445 return retval;
4446}
4447
4448/*
4449 * Put file name into IObuff with quotes.
4450 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004451 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004452msg_add_fname(buf, fname)
4453 buf_T *buf;
4454 char_u *fname;
4455{
4456 if (fname == NULL)
4457 fname = (char_u *)"-stdin-";
4458 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4459 IObuff[0] = '"';
4460 STRCAT(IObuff, "\" ");
4461}
4462
4463/*
4464 * Append message for text mode to IObuff.
4465 * Return TRUE if something appended.
4466 */
4467 static int
4468msg_add_fileformat(eol_type)
4469 int eol_type;
4470{
4471#ifndef USE_CRNL
4472 if (eol_type == EOL_DOS)
4473 {
4474 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4475 return TRUE;
4476 }
4477#endif
4478#ifndef USE_CR
4479 if (eol_type == EOL_MAC)
4480 {
4481 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4482 return TRUE;
4483 }
4484#endif
4485#if defined(USE_CRNL) || defined(USE_CR)
4486 if (eol_type == EOL_UNIX)
4487 {
4488 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4489 return TRUE;
4490 }
4491#endif
4492 return FALSE;
4493}
4494
4495/*
4496 * Append line and character count to IObuff.
4497 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004498 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004499msg_add_lines(insert_space, lnum, nchars)
4500 int insert_space;
4501 long lnum;
4502 long nchars;
4503{
4504 char_u *p;
4505
4506 p = IObuff + STRLEN(IObuff);
4507
4508 if (insert_space)
4509 *p++ = ' ';
4510 if (shortmess(SHM_LINES))
4511 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4512 else
4513 {
4514 if (lnum == 1)
4515 STRCPY(p, _("1 line, "));
4516 else
4517 sprintf((char *)p, _("%ld lines, "), lnum);
4518 p += STRLEN(p);
4519 if (nchars == 1)
4520 STRCPY(p, _("1 character"));
4521 else
4522 sprintf((char *)p, _("%ld characters"), nchars);
4523 }
4524}
4525
4526/*
4527 * Append message for missing line separator to IObuff.
4528 */
4529 static void
4530msg_add_eol()
4531{
4532 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4533}
4534
4535/*
4536 * Check modification time of file, before writing to it.
4537 * The size isn't checked, because using a tool like "gzip" takes care of
4538 * using the same timestamp but can't set the size.
4539 */
4540 static int
4541check_mtime(buf, st)
4542 buf_T *buf;
4543 struct stat *st;
4544{
4545 if (buf->b_mtime_read != 0
4546 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4547 {
4548 msg_scroll = TRUE; /* don't overwrite messages here */
4549 msg_silent = 0; /* must give this prompt */
4550 /* don't use emsg() here, don't want to flush the buffers */
4551 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4552 hl_attr(HLF_E));
4553 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4554 TRUE) == 'n')
4555 return FAIL;
4556 msg_scroll = FALSE; /* always overwrite the file message now */
4557 }
4558 return OK;
4559}
4560
4561 static int
4562time_differs(t1, t2)
4563 long t1, t2;
4564{
4565#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4566 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4567 * the seconds. Since the roundoff is done when flushing the inode, the
4568 * time may change unexpectedly by one second!!! */
4569 return (t1 - t2 > 1 || t2 - t1 > 1);
4570#else
4571 return (t1 != t2);
4572#endif
4573}
4574
4575/*
4576 * Call write() to write a number of bytes to the file.
4577 * Also handles encryption and 'encoding' conversion.
4578 *
4579 * Return FAIL for failure, OK otherwise.
4580 */
4581 static int
4582buf_write_bytes(ip)
4583 struct bw_info *ip;
4584{
4585 int wlen;
4586 char_u *buf = ip->bw_buf; /* data to write */
4587 int len = ip->bw_len; /* length of data */
4588#ifdef HAS_BW_FLAGS
4589 int flags = ip->bw_flags; /* extra flags */
4590#endif
4591
4592#ifdef FEAT_MBYTE
4593 /*
4594 * Skip conversion when writing the crypt magic number or the BOM.
4595 */
4596 if (!(flags & FIO_NOCONVERT))
4597 {
4598 char_u *p;
4599 unsigned c;
4600 int n;
4601
4602 if (flags & FIO_UTF8)
4603 {
4604 /*
4605 * Convert latin1 in the buffer to UTF-8 in the file.
4606 */
4607 p = ip->bw_conv_buf; /* translate to buffer */
4608 for (wlen = 0; wlen < len; ++wlen)
4609 p += utf_char2bytes(buf[wlen], p);
4610 buf = ip->bw_conv_buf;
4611 len = (int)(p - ip->bw_conv_buf);
4612 }
4613 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4614 {
4615 /*
4616 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4617 * Latin1 chars in the file.
4618 */
4619 if (flags & FIO_LATIN1)
4620 p = buf; /* translate in-place (can only get shorter) */
4621 else
4622 p = ip->bw_conv_buf; /* translate to buffer */
4623 for (wlen = 0; wlen < len; wlen += n)
4624 {
4625 if (wlen == 0 && ip->bw_restlen != 0)
4626 {
4627 int l;
4628
4629 /* Use remainder of previous call. Append the start of
4630 * buf[] to get a full sequence. Might still be too
4631 * short! */
4632 l = CONV_RESTLEN - ip->bw_restlen;
4633 if (l > len)
4634 l = len;
4635 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004636 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637 if (n > ip->bw_restlen + len)
4638 {
4639 /* We have an incomplete byte sequence at the end to
4640 * be written. We can't convert it without the
4641 * remaining bytes. Keep them for the next call. */
4642 if (ip->bw_restlen + len > CONV_RESTLEN)
4643 return FAIL;
4644 ip->bw_restlen += len;
4645 break;
4646 }
4647 if (n > 1)
4648 c = utf_ptr2char(ip->bw_rest);
4649 else
4650 c = ip->bw_rest[0];
4651 if (n >= ip->bw_restlen)
4652 {
4653 n -= ip->bw_restlen;
4654 ip->bw_restlen = 0;
4655 }
4656 else
4657 {
4658 ip->bw_restlen -= n;
4659 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4660 (size_t)ip->bw_restlen);
4661 n = 0;
4662 }
4663 }
4664 else
4665 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004666 n = utf_ptr2len_len(buf + wlen, len - wlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004667 if (n > len - wlen)
4668 {
4669 /* We have an incomplete byte sequence at the end to
4670 * be written. We can't convert it without the
4671 * remaining bytes. Keep them for the next call. */
4672 if (len - wlen > CONV_RESTLEN)
4673 return FAIL;
4674 ip->bw_restlen = len - wlen;
4675 mch_memmove(ip->bw_rest, buf + wlen,
4676 (size_t)ip->bw_restlen);
4677 break;
4678 }
4679 if (n > 1)
4680 c = utf_ptr2char(buf + wlen);
4681 else
4682 c = buf[wlen];
4683 }
4684
4685 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4686 }
4687 if (flags & FIO_LATIN1)
4688 len = (int)(p - buf);
4689 else
4690 {
4691 buf = ip->bw_conv_buf;
4692 len = (int)(p - ip->bw_conv_buf);
4693 }
4694 }
4695
4696# ifdef WIN3264
4697 else if (flags & FIO_CODEPAGE)
4698 {
4699 /*
4700 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
4701 * codepage.
4702 */
4703 char_u *from;
4704 size_t fromlen;
4705 char_u *to;
4706 int u8c;
4707 BOOL bad = FALSE;
4708 int needed;
4709
4710 if (ip->bw_restlen > 0)
4711 {
4712 /* Need to concatenate the remainder of the previous call and
4713 * the bytes of the current call. Use the end of the
4714 * conversion buffer for this. */
4715 fromlen = len + ip->bw_restlen;
4716 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4717 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4718 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4719 }
4720 else
4721 {
4722 from = buf;
4723 fromlen = len;
4724 }
4725
4726 to = ip->bw_conv_buf;
4727 if (enc_utf8)
4728 {
4729 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
4730 * The buffer has been allocated to be big enough. */
4731 while (fromlen > 0)
4732 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004733 n = utf_ptr2len_len(from, fromlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004734 if (n > (int)fromlen) /* incomplete byte sequence */
4735 break;
4736 u8c = utf_ptr2char(from);
4737 *to++ = (u8c & 0xff);
4738 *to++ = (u8c >> 8);
4739 fromlen -= n;
4740 from += n;
4741 }
4742
4743 /* Copy remainder to ip->bw_rest[] to be used for the next
4744 * call. */
4745 if (fromlen > CONV_RESTLEN)
4746 {
4747 /* weird overlong sequence */
4748 ip->bw_conv_error = TRUE;
4749 return FAIL;
4750 }
4751 mch_memmove(ip->bw_rest, from, fromlen);
4752 ip->bw_restlen = fromlen;
4753 }
4754 else
4755 {
4756 /* Convert from enc_codepage to UCS-2, to the start of the
4757 * buffer. The buffer has been allocated to be big enough. */
4758 ip->bw_restlen = 0;
4759 needed = MultiByteToWideChar(enc_codepage,
4760 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
4761 NULL, 0);
4762 if (needed == 0)
4763 {
4764 /* When conversion fails there may be a trailing byte. */
4765 needed = MultiByteToWideChar(enc_codepage,
4766 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
4767 NULL, 0);
4768 if (needed == 0)
4769 {
4770 /* Conversion doesn't work. */
4771 ip->bw_conv_error = TRUE;
4772 return FAIL;
4773 }
4774 /* Save the trailing byte for the next call. */
4775 ip->bw_rest[0] = from[fromlen - 1];
4776 ip->bw_restlen = 1;
4777 }
4778 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
4779 (LPCSTR)from, fromlen - ip->bw_restlen,
4780 (LPWSTR)to, needed);
4781 if (needed == 0)
4782 {
4783 /* Safety check: Conversion doesn't work. */
4784 ip->bw_conv_error = TRUE;
4785 return FAIL;
4786 }
4787 to += needed * 2;
4788 }
4789
4790 fromlen = to - ip->bw_conv_buf;
4791 buf = to;
4792# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
4793 if (FIO_GET_CP(flags) == CP_UTF8)
4794 {
4795 /* Convert from UCS-2 to UTF-8, using the remainder of the
4796 * conversion buffer. Fails when out of space. */
4797 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
4798 {
4799 u8c = *from++;
4800 u8c += (*from++ << 8);
4801 to += utf_char2bytes(u8c, to);
4802 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
4803 {
4804 ip->bw_conv_error = TRUE;
4805 return FAIL;
4806 }
4807 }
4808 len = to - buf;
4809 }
4810 else
4811#endif
4812 {
4813 /* Convert from UCS-2 to the codepage, using the remainder of
4814 * the conversion buffer. If the conversion uses the default
4815 * character "0", the data doesn't fit in this encoding, so
4816 * fail. */
4817 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
4818 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
4819 (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
4820 if (bad)
4821 {
4822 ip->bw_conv_error = TRUE;
4823 return FAIL;
4824 }
4825 }
4826 }
4827# endif
4828
4829# ifdef MACOS_X
4830 else if (flags & FIO_MACROMAN)
4831 {
4832 /*
4833 * Convert UTF-8 or latin1 to Apple MacRoman.
4834 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004835 char_u *from;
4836 size_t fromlen;
4837
4838 if (ip->bw_restlen > 0)
4839 {
4840 /* Need to concatenate the remainder of the previous call and
4841 * the bytes of the current call. Use the end of the
4842 * conversion buffer for this. */
4843 fromlen = len + ip->bw_restlen;
4844 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4845 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4846 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4847 }
4848 else
4849 {
4850 from = buf;
4851 fromlen = len;
4852 }
4853
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004854 if (enc2macroman(from, fromlen,
4855 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
4856 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004857 {
4858 ip->bw_conv_error = TRUE;
4859 return FAIL;
4860 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004861 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004862 }
4863# endif
4864
4865# ifdef USE_ICONV
4866 if (ip->bw_iconv_fd != (iconv_t)-1)
4867 {
4868 const char *from;
4869 size_t fromlen;
4870 char *to;
4871 size_t tolen;
4872
4873 /* Convert with iconv(). */
4874 if (ip->bw_restlen > 0)
4875 {
4876 /* Need to concatenate the remainder of the previous call and
4877 * the bytes of the current call. Use the end of the
4878 * conversion buffer for this. */
4879 fromlen = len + ip->bw_restlen;
4880 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4881 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
4882 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
4883 tolen = ip->bw_conv_buflen - fromlen;
4884 }
4885 else
4886 {
4887 from = (const char *)buf;
4888 fromlen = len;
4889 tolen = ip->bw_conv_buflen;
4890 }
4891 to = (char *)ip->bw_conv_buf;
4892
4893 if (ip->bw_first)
4894 {
4895 size_t save_len = tolen;
4896
4897 /* output the initial shift state sequence */
4898 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
4899
4900 /* There is a bug in iconv() on Linux (which appears to be
4901 * wide-spread) which sets "to" to NULL and messes up "tolen".
4902 */
4903 if (to == NULL)
4904 {
4905 to = (char *)ip->bw_conv_buf;
4906 tolen = save_len;
4907 }
4908 ip->bw_first = FALSE;
4909 }
4910
4911 /*
4912 * If iconv() has an error or there is not enough room, fail.
4913 */
4914 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
4915 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
4916 || fromlen > CONV_RESTLEN)
4917 {
4918 ip->bw_conv_error = TRUE;
4919 return FAIL;
4920 }
4921
4922 /* copy remainder to ip->bw_rest[] to be used for the next call. */
4923 if (fromlen > 0)
4924 mch_memmove(ip->bw_rest, (void *)from, fromlen);
4925 ip->bw_restlen = (int)fromlen;
4926
4927 buf = ip->bw_conv_buf;
4928 len = (int)((char_u *)to - ip->bw_conv_buf);
4929 }
4930# endif
4931 }
4932#endif /* FEAT_MBYTE */
4933
4934#ifdef FEAT_CRYPT
4935 if (flags & FIO_ENCRYPTED) /* encrypt the data */
4936 {
4937 int ztemp, t, i;
4938
4939 for (i = 0; i < len; i++)
4940 {
4941 ztemp = buf[i];
4942 buf[i] = ZENCODE(ztemp, t);
4943 }
4944 }
4945#endif
4946
4947 /* Repeat the write(), it may be interrupted by a signal. */
4948 while (len)
4949 {
4950 wlen = vim_write(ip->bw_fd, buf, len);
4951 if (wlen <= 0) /* error! */
4952 return FAIL;
4953 len -= wlen;
4954 buf += wlen;
4955 }
4956 return OK;
4957}
4958
4959#ifdef FEAT_MBYTE
4960/*
4961 * Convert a Unicode character to bytes.
4962 */
4963 static int
4964ucs2bytes(c, pp, flags)
4965 unsigned c; /* in: character */
4966 char_u **pp; /* in/out: pointer to result */
4967 int flags; /* FIO_ flags */
4968{
4969 char_u *p = *pp;
4970 int error = FALSE;
4971 int cc;
4972
4973
4974 if (flags & FIO_UCS4)
4975 {
4976 if (flags & FIO_ENDIAN_L)
4977 {
4978 *p++ = c;
4979 *p++ = (c >> 8);
4980 *p++ = (c >> 16);
4981 *p++ = (c >> 24);
4982 }
4983 else
4984 {
4985 *p++ = (c >> 24);
4986 *p++ = (c >> 16);
4987 *p++ = (c >> 8);
4988 *p++ = c;
4989 }
4990 }
4991 else if (flags & (FIO_UCS2 | FIO_UTF16))
4992 {
4993 if (c >= 0x10000)
4994 {
4995 if (flags & FIO_UTF16)
4996 {
4997 /* Make two words, ten bits of the character in each. First
4998 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
4999 c -= 0x10000;
5000 if (c >= 0x100000)
5001 error = TRUE;
5002 cc = ((c >> 10) & 0x3ff) + 0xd800;
5003 if (flags & FIO_ENDIAN_L)
5004 {
5005 *p++ = cc;
5006 *p++ = ((unsigned)cc >> 8);
5007 }
5008 else
5009 {
5010 *p++ = ((unsigned)cc >> 8);
5011 *p++ = cc;
5012 }
5013 c = (c & 0x3ff) + 0xdc00;
5014 }
5015 else
5016 error = TRUE;
5017 }
5018 if (flags & FIO_ENDIAN_L)
5019 {
5020 *p++ = c;
5021 *p++ = (c >> 8);
5022 }
5023 else
5024 {
5025 *p++ = (c >> 8);
5026 *p++ = c;
5027 }
5028 }
5029 else /* Latin1 */
5030 {
5031 if (c >= 0x100)
5032 {
5033 error = TRUE;
5034 *p++ = 0xBF;
5035 }
5036 else
5037 *p++ = c;
5038 }
5039
5040 *pp = p;
5041 return error;
5042}
5043
5044/*
5045 * Return TRUE if "a" and "b" are the same 'encoding'.
5046 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5047 */
5048 static int
5049same_encoding(a, b)
5050 char_u *a;
5051 char_u *b;
5052{
5053 int f;
5054
5055 if (STRCMP(a, b) == 0)
5056 return TRUE;
5057 f = get_fio_flags(a);
5058 return (f != 0 && get_fio_flags(b) == f);
5059}
5060
5061/*
5062 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5063 * internal conversion.
5064 * if "ptr" is an empty string, use 'encoding'.
5065 */
5066 static int
5067get_fio_flags(ptr)
5068 char_u *ptr;
5069{
5070 int prop;
5071
5072 if (*ptr == NUL)
5073 ptr = p_enc;
5074
5075 prop = enc_canon_props(ptr);
5076 if (prop & ENC_UNICODE)
5077 {
5078 if (prop & ENC_2BYTE)
5079 {
5080 if (prop & ENC_ENDIAN_L)
5081 return FIO_UCS2 | FIO_ENDIAN_L;
5082 return FIO_UCS2;
5083 }
5084 if (prop & ENC_4BYTE)
5085 {
5086 if (prop & ENC_ENDIAN_L)
5087 return FIO_UCS4 | FIO_ENDIAN_L;
5088 return FIO_UCS4;
5089 }
5090 if (prop & ENC_2WORD)
5091 {
5092 if (prop & ENC_ENDIAN_L)
5093 return FIO_UTF16 | FIO_ENDIAN_L;
5094 return FIO_UTF16;
5095 }
5096 return FIO_UTF8;
5097 }
5098 if (prop & ENC_LATIN1)
5099 return FIO_LATIN1;
5100 /* must be ENC_DBCS, requires iconv() */
5101 return 0;
5102}
5103
5104#ifdef WIN3264
5105/*
5106 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5107 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5108 * Used for conversion between 'encoding' and 'fileencoding'.
5109 */
5110 static int
5111get_win_fio_flags(ptr)
5112 char_u *ptr;
5113{
5114 int cp;
5115
5116 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5117 if (!enc_utf8 && enc_codepage <= 0)
5118 return 0;
5119
5120 cp = encname2codepage(ptr);
5121 if (cp == 0)
5122 {
5123# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5124 if (STRCMP(ptr, "utf-8") == 0)
5125 cp = CP_UTF8;
5126 else
5127# endif
5128 return 0;
5129 }
5130 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5131}
5132#endif
5133
5134#ifdef MACOS_X
5135/*
5136 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5137 * needed for the internal conversion to/from utf-8 or latin1.
5138 */
5139 static int
5140get_mac_fio_flags(ptr)
5141 char_u *ptr;
5142{
5143 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5144 && (enc_canon_props(ptr) & ENC_MACROMAN))
5145 return FIO_MACROMAN;
5146 return 0;
5147}
5148#endif
5149
5150/*
5151 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5152 * "size" must be at least 2.
5153 * Return the name of the encoding and set "*lenp" to the length.
5154 * Returns NULL when no BOM found.
5155 */
5156 static char_u *
5157check_for_bom(p, size, lenp, flags)
5158 char_u *p;
5159 long size;
5160 int *lenp;
5161 int flags;
5162{
5163 char *name = NULL;
5164 int len = 2;
5165
5166 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5167 && (flags == FIO_ALL || flags == 0))
5168 {
5169 name = "utf-8"; /* EF BB BF */
5170 len = 3;
5171 }
5172 else if (p[0] == 0xff && p[1] == 0xfe)
5173 {
5174 if (size >= 4 && p[2] == 0 && p[3] == 0
5175 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5176 {
5177 name = "ucs-4le"; /* FF FE 00 00 */
5178 len = 4;
5179 }
5180 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5181 name = "ucs-2le"; /* FF FE */
5182 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5183 name = "utf-16le"; /* FF FE */
5184 }
5185 else if (p[0] == 0xfe && p[1] == 0xff
5186 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5187 {
5188 if (flags == FIO_UTF16)
5189 name = "utf-16"; /* FE FF */
5190 else
5191 name = "ucs-2"; /* FE FF */
5192 }
5193 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5194 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5195 {
5196 name = "ucs-4"; /* 00 00 FE FF */
5197 len = 4;
5198 }
5199
5200 *lenp = len;
5201 return (char_u *)name;
5202}
5203
5204/*
5205 * Generate a BOM in "buf[4]" for encoding "name".
5206 * Return the length of the BOM (zero when no BOM).
5207 */
5208 static int
5209make_bom(buf, name)
5210 char_u *buf;
5211 char_u *name;
5212{
5213 int flags;
5214 char_u *p;
5215
5216 flags = get_fio_flags(name);
5217
5218 /* Can't put a BOM in a non-Unicode file. */
5219 if (flags == FIO_LATIN1 || flags == 0)
5220 return 0;
5221
5222 if (flags == FIO_UTF8) /* UTF-8 */
5223 {
5224 buf[0] = 0xef;
5225 buf[1] = 0xbb;
5226 buf[2] = 0xbf;
5227 return 3;
5228 }
5229 p = buf;
5230 (void)ucs2bytes(0xfeff, &p, flags);
5231 return (int)(p - buf);
5232}
5233#endif
5234
5235/*
5236 * Try to find a shortname by comparing the fullname with the current
5237 * directory.
5238 * Returns NULL if not shorter name possible, pointer into "full_path"
5239 * otherwise.
5240 */
5241 char_u *
5242shorten_fname(full_path, dir_name)
5243 char_u *full_path;
5244 char_u *dir_name;
5245{
5246 int len;
5247 char_u *p;
5248
5249 if (full_path == NULL)
5250 return NULL;
5251 len = (int)STRLEN(dir_name);
5252 if (fnamencmp(dir_name, full_path, len) == 0)
5253 {
5254 p = full_path + len;
5255#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5256 /*
5257 * MSDOS: when a file is in the root directory, dir_name will end in a
5258 * slash, since C: by itself does not define a specific dir. In this
5259 * case p may already be correct. <negri>
5260 */
5261 if (!((len > 2) && (*(p - 2) == ':')))
5262#endif
5263 {
5264 if (vim_ispathsep(*p))
5265 ++p;
5266#ifndef VMS /* the path separator is always part of the path */
5267 else
5268 p = NULL;
5269#endif
5270 }
5271 }
5272#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5273 /*
5274 * When using a file in the current drive, remove the drive name:
5275 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5276 * a floppy from "A:\dir" to "B:\dir".
5277 */
5278 else if (len > 3
5279 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5280 && full_path[1] == ':'
5281 && vim_ispathsep(full_path[2]))
5282 p = full_path + 2;
5283#endif
5284 else
5285 p = NULL;
5286 return p;
5287}
5288
5289/*
5290 * Shorten filenames for all buffers.
5291 * When "force" is TRUE: Use full path from now on for files currently being
5292 * edited, both for file name and swap file name. Try to shorten the file
5293 * names a bit, if safe to do so.
5294 * When "force" is FALSE: Only try to shorten absolute file names.
5295 * For buffers that have buftype "nofile" or "scratch": never change the file
5296 * name.
5297 */
5298 void
5299shorten_fnames(force)
5300 int force;
5301{
5302 char_u dirname[MAXPATHL];
5303 buf_T *buf;
5304 char_u *p;
5305
5306 mch_dirname(dirname, MAXPATHL);
5307 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5308 {
5309 if (buf->b_fname != NULL
5310#ifdef FEAT_QUICKFIX
5311 && !bt_nofile(buf)
5312#endif
5313 && !path_with_url(buf->b_fname)
5314 && (force
5315 || buf->b_sfname == NULL
5316 || mch_isFullName(buf->b_sfname)))
5317 {
5318 vim_free(buf->b_sfname);
5319 buf->b_sfname = NULL;
5320 p = shorten_fname(buf->b_ffname, dirname);
5321 if (p != NULL)
5322 {
5323 buf->b_sfname = vim_strsave(p);
5324 buf->b_fname = buf->b_sfname;
5325 }
5326 if (p == NULL || buf->b_fname == NULL)
5327 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005328 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005329
5330 /* Always make the swap file name a full path, a "nofile" buffer may
5331 * also have a swap file. */
5332 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005333 }
5334#ifdef FEAT_WINDOWS
5335 status_redraw_all();
5336#endif
5337}
5338
5339#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5340 || defined(FEAT_GUI_MSWIN) \
5341 || defined(FEAT_GUI_MAC) \
5342 || defined(PROTO)
5343/*
5344 * Shorten all filenames in "fnames[count]" by current directory.
5345 */
5346 void
5347shorten_filenames(fnames, count)
5348 char_u **fnames;
5349 int count;
5350{
5351 int i;
5352 char_u dirname[MAXPATHL];
5353 char_u *p;
5354
5355 if (fnames == NULL || count < 1)
5356 return;
5357 mch_dirname(dirname, sizeof(dirname));
5358 for (i = 0; i < count; ++i)
5359 {
5360 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5361 {
5362 /* shorten_fname() returns pointer in given "fnames[i]". If free
5363 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5364 * "p" first then free fnames[i]. */
5365 p = vim_strsave(p);
5366 vim_free(fnames[i]);
5367 fnames[i] = p;
5368 }
5369 }
5370}
5371#endif
5372
5373/*
5374 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5375 * fo_o_h.ext for MSDOS or when shortname option set.
5376 *
5377 * Assumed that fname is a valid name found in the filesystem we assure that
5378 * the return value is a different name and ends in 'ext'.
5379 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5380 * characters otherwise.
5381 * Space for the returned name is allocated, must be freed later.
5382 * Returns NULL when out of memory.
5383 */
5384 char_u *
5385modname(fname, ext, prepend_dot)
5386 char_u *fname, *ext;
5387 int prepend_dot; /* may prepend a '.' to file name */
5388{
5389 return buf_modname(
5390#ifdef SHORT_FNAME
5391 TRUE,
5392#else
5393 (curbuf->b_p_sn || curbuf->b_shortname),
5394#endif
5395 fname, ext, prepend_dot);
5396}
5397
5398 char_u *
5399buf_modname(shortname, fname, ext, prepend_dot)
5400 int shortname; /* use 8.3 file name */
5401 char_u *fname, *ext;
5402 int prepend_dot; /* may prepend a '.' to file name */
5403{
5404 char_u *retval;
5405 char_u *s;
5406 char_u *e;
5407 char_u *ptr;
5408 int fnamelen, extlen;
5409
5410 extlen = (int)STRLEN(ext);
5411
5412 /*
5413 * If there is no file name we must get the name of the current directory
5414 * (we need the full path in case :cd is used).
5415 */
5416 if (fname == NULL || *fname == NUL)
5417 {
5418 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5419 if (retval == NULL)
5420 return NULL;
5421 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5422 (fnamelen = (int)STRLEN(retval)) == 0)
5423 {
5424 vim_free(retval);
5425 return NULL;
5426 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005427 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 {
5429 retval[fnamelen++] = PATHSEP;
5430 retval[fnamelen] = NUL;
5431 }
5432#ifndef SHORT_FNAME
5433 prepend_dot = FALSE; /* nothing to prepend a dot to */
5434#endif
5435 }
5436 else
5437 {
5438 fnamelen = (int)STRLEN(fname);
5439 retval = alloc((unsigned)(fnamelen + extlen + 3));
5440 if (retval == NULL)
5441 return NULL;
5442 STRCPY(retval, fname);
5443#ifdef VMS
5444 vms_remove_version(retval); /* we do not need versions here */
5445#endif
5446 }
5447
5448 /*
5449 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5450 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5451 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5452 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5453 */
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005454 for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455 {
5456#ifndef RISCOS
5457 if (*ext == '.'
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005458# ifdef USE_LONG_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005459 && (!USE_LONG_FNAME || shortname)
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005460# else
5461# ifndef SHORT_FNAME
Bram Moolenaar071d4272004-06-13 20:20:40 +00005462 && shortname
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005463# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005464# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005465 )
5466 if (*ptr == '.') /* replace '.' by '_' */
5467 *ptr = '_';
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005468#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469 if (vim_ispathsep(*ptr))
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005470 {
5471 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005472 break;
Bram Moolenaar53180ce2005-07-05 21:48:14 +00005473 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005474 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005475
5476 /* the file name has at most BASENAMELEN characters. */
5477#ifndef SHORT_FNAME
5478 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5479 ptr[BASENAMELEN] = '\0';
5480#endif
5481
5482 s = ptr + STRLEN(ptr);
5483
5484 /*
5485 * For 8.3 file names we may have to reduce the length.
5486 */
5487#ifdef USE_LONG_FNAME
5488 if (!USE_LONG_FNAME || shortname)
5489#else
5490# ifndef SHORT_FNAME
5491 if (shortname)
5492# endif
5493#endif
5494 {
5495 /*
5496 * If there is no file name, or the file name ends in '/', and the
5497 * extension starts with '.', put a '_' before the dot, because just
5498 * ".ext" is invalid.
5499 */
5500 if (fname == NULL || *fname == NUL
5501 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5502 {
5503#ifdef RISCOS
5504 if (*ext == '/')
5505#else
5506 if (*ext == '.')
5507#endif
5508 *s++ = '_';
5509 }
5510 /*
5511 * If the extension starts with '.', truncate the base name at 8
5512 * characters
5513 */
5514#ifdef RISCOS
5515 /* We normally use '/', but swap files are '_' */
5516 else if (*ext == '/' || *ext == '_')
5517#else
5518 else if (*ext == '.')
5519#endif
5520 {
5521 if (s - ptr > (size_t)8)
5522 {
5523 s = ptr + 8;
5524 *s = '\0';
5525 }
5526 }
5527 /*
5528 * If the extension doesn't start with '.', and the file name
5529 * doesn't have an extension yet, append a '.'
5530 */
5531#ifdef RISCOS
5532 else if ((e = vim_strchr(ptr, '/')) == NULL)
5533 *s++ = '/';
5534#else
5535 else if ((e = vim_strchr(ptr, '.')) == NULL)
5536 *s++ = '.';
5537#endif
5538 /*
5539 * If the extension doesn't start with '.', and there already is an
5540 * extension, it may need to be tructated
5541 */
5542 else if ((int)STRLEN(e) + extlen > 4)
5543 s = e + 4 - extlen;
5544 }
5545#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5546 /*
5547 * If there is no file name, and the extension starts with '.', put a
5548 * '_' before the dot, because just ".ext" may be invalid if it's on a
5549 * FAT partition, and on HPFS it doesn't matter.
5550 */
5551 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5552 *s++ = '_';
5553#endif
5554
5555 /*
5556 * Append the extention.
5557 * ext can start with '.' and cannot exceed 3 more characters.
5558 */
5559 STRCPY(s, ext);
5560
5561#ifndef SHORT_FNAME
5562 /*
5563 * Prepend the dot.
5564 */
5565 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5566#ifdef RISCOS
5567 '/'
5568#else
5569 '.'
5570#endif
5571#ifdef USE_LONG_FNAME
5572 && USE_LONG_FNAME
5573#endif
5574 )
5575 {
5576 mch_memmove(e + 1, e, STRLEN(e) + 1);
5577#ifdef RISCOS
5578 *e = '/';
5579#else
5580 *e = '.';
5581#endif
5582 }
5583#endif
5584
5585 /*
5586 * Check that, after appending the extension, the file name is really
5587 * different.
5588 */
5589 if (fname != NULL && STRCMP(fname, retval) == 0)
5590 {
5591 /* we search for a character that can be replaced by '_' */
5592 while (--s >= ptr)
5593 {
5594 if (*s != '_')
5595 {
5596 *s = '_';
5597 break;
5598 }
5599 }
5600 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5601 *ptr = 'v';
5602 }
5603 return retval;
5604}
5605
5606/*
5607 * Like fgets(), but if the file line is too long, it is truncated and the
5608 * rest of the line is thrown away. Returns TRUE for end-of-file.
5609 */
5610 int
5611vim_fgets(buf, size, fp)
5612 char_u *buf;
5613 int size;
5614 FILE *fp;
5615{
5616 char *eof;
5617#define FGETS_SIZE 200
5618 char tbuf[FGETS_SIZE];
5619
5620 buf[size - 2] = NUL;
5621#ifdef USE_CR
5622 eof = fgets_cr((char *)buf, size, fp);
5623#else
5624 eof = fgets((char *)buf, size, fp);
5625#endif
5626 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5627 {
5628 buf[size - 1] = NUL; /* Truncate the line */
5629
5630 /* Now throw away the rest of the line: */
5631 do
5632 {
5633 tbuf[FGETS_SIZE - 2] = NUL;
5634#ifdef USE_CR
5635 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5636#else
5637 fgets((char *)tbuf, FGETS_SIZE, fp);
5638#endif
5639 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5640 }
5641 return (eof == NULL);
5642}
5643
5644#if defined(USE_CR) || defined(PROTO)
5645/*
5646 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5647 * Returns TRUE for end-of-file.
5648 * Only used for the Mac, because it's much slower than vim_fgets().
5649 */
5650 int
5651tag_fgets(buf, size, fp)
5652 char_u *buf;
5653 int size;
5654 FILE *fp;
5655{
5656 int i = 0;
5657 int c;
5658 int eof = FALSE;
5659
5660 for (;;)
5661 {
5662 c = fgetc(fp);
5663 if (c == EOF)
5664 {
5665 eof = TRUE;
5666 break;
5667 }
5668 if (c == '\r')
5669 {
5670 /* Always store a NL for end-of-line. */
5671 if (i < size - 1)
5672 buf[i++] = '\n';
5673 c = fgetc(fp);
5674 if (c != '\n') /* Macintosh format: single CR. */
5675 ungetc(c, fp);
5676 break;
5677 }
5678 if (i < size - 1)
5679 buf[i++] = c;
5680 if (c == '\n')
5681 break;
5682 }
5683 buf[i] = NUL;
5684 return eof;
5685}
5686#endif
5687
5688/*
5689 * rename() only works if both files are on the same file system, this
5690 * function will (attempts to?) copy the file across if rename fails -- webb
5691 * Return -1 for failure, 0 for success.
5692 */
5693 int
5694vim_rename(from, to)
5695 char_u *from;
5696 char_u *to;
5697{
5698 int fd_in;
5699 int fd_out;
5700 int n;
5701 char *errmsg = NULL;
5702 char *buffer;
5703#ifdef AMIGA
5704 BPTR flock;
5705#endif
5706 struct stat st;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005707 long perm;
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005708#ifdef HAVE_ACL
5709 vim_acl_T acl; /* ACL from original file */
5710#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005711
5712 /*
5713 * When the names are identical, there is nothing to do.
5714 */
5715 if (fnamecmp(from, to) == 0)
5716 return 0;
5717
5718 /*
5719 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
5720 */
5721 if (mch_stat((char *)from, &st) < 0)
5722 return -1;
5723
5724 /*
5725 * Delete the "to" file, this is required on some systems to make the
5726 * mch_rename() work, on other systems it makes sure that we don't have
5727 * two files when the mch_rename() fails.
5728 */
5729
5730#ifdef AMIGA
5731 /*
5732 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
5733 * that the name of the "to" file is the same as the "from" file, even
5734 * though the names are different. To avoid the chance of accidently
5735 * deleting the "from" file (horror!) we lock it during the remove.
5736 *
5737 * When used for making a backup before writing the file: This should not
5738 * happen with ":w", because startscript() should detect this problem and
5739 * set buf->b_shortname, causing modname() to return a correct ".bak" file
5740 * name. This problem does exist with ":w filename", but then the
5741 * original file will be somewhere else so the backup isn't really
5742 * important. If autoscripting is off the rename may fail.
5743 */
5744 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
5745#endif
5746 mch_remove(to);
5747#ifdef AMIGA
5748 if (flock)
5749 UnLock(flock);
5750#endif
5751
5752 /*
5753 * First try a normal rename, return if it works.
5754 */
5755 if (mch_rename((char *)from, (char *)to) == 0)
5756 return 0;
5757
5758 /*
5759 * Rename() failed, try copying the file.
5760 */
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005761 perm = mch_getperm(from);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005762#ifdef HAVE_ACL
5763 /* For systems that support ACL: get the ACL from the original file. */
5764 acl = mch_get_acl(from);
5765#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005766 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
5767 if (fd_in == -1)
5768 return -1;
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005769
5770 /* Create the new file with same permissions as the original. */
Bram Moolenaara5792f52005-11-23 21:25:05 +00005771 fd_out = mch_open((char *)to,
5772 O_CREAT|O_EXCL|O_WRONLY|O_EXTRA|O_NOFOLLOW, (int)perm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005773 if (fd_out == -1)
5774 {
5775 close(fd_in);
5776 return -1;
5777 }
5778
5779 buffer = (char *)alloc(BUFSIZE);
5780 if (buffer == NULL)
5781 {
5782 close(fd_in);
5783 close(fd_out);
5784 return -1;
5785 }
5786
5787 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
5788 if (vim_write(fd_out, buffer, n) != n)
5789 {
5790 errmsg = _("E208: Error writing to \"%s\"");
5791 break;
5792 }
5793
5794 vim_free(buffer);
5795 close(fd_in);
5796 if (close(fd_out) < 0)
5797 errmsg = _("E209: Error closing \"%s\"");
5798 if (n < 0)
5799 {
5800 errmsg = _("E210: Error reading \"%s\"");
5801 to = from;
5802 }
Bram Moolenaar9be038d2005-03-08 22:34:32 +00005803 mch_setperm(to, perm);
Bram Moolenaarcd71fa32005-03-11 22:46:48 +00005804#ifdef HAVE_ACL
5805 mch_set_acl(to, acl);
5806#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005807 if (errmsg != NULL)
5808 {
5809 EMSG2(errmsg, to);
5810 return -1;
5811 }
5812 mch_remove(from);
5813 return 0;
5814}
5815
5816static int already_warned = FALSE;
5817
5818/*
5819 * Check if any not hidden buffer has been changed.
5820 * Postpone the check if there are characters in the stuff buffer, a global
5821 * command is being executed, a mapping is being executed or an autocommand is
5822 * busy.
5823 * Returns TRUE if some message was written (screen should be redrawn and
5824 * cursor positioned).
5825 */
5826 int
5827check_timestamps(focus)
5828 int focus; /* called for GUI focus event */
5829{
5830 buf_T *buf;
5831 int didit = 0;
5832 int n;
5833
5834 /* Don't check timestamps while system() or another low-level function may
5835 * cause us to lose and gain focus. */
5836 if (no_check_timestamps > 0)
5837 return FALSE;
5838
5839 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
5840 * event and we would keep on checking if the file is steadily growing.
5841 * Do check again after typing something. */
5842 if (focus && did_check_timestamps)
5843 {
5844 need_check_timestamps = TRUE;
5845 return FALSE;
5846 }
5847
5848 if (!stuff_empty() || global_busy || !typebuf_typed()
5849#ifdef FEAT_AUTOCMD
5850 || autocmd_busy
5851#endif
5852 )
5853 need_check_timestamps = TRUE; /* check later */
5854 else
5855 {
5856 ++no_wait_return;
5857 did_check_timestamps = TRUE;
5858 already_warned = FALSE;
5859 for (buf = firstbuf; buf != NULL; )
5860 {
5861 /* Only check buffers in a window. */
5862 if (buf->b_nwindows > 0)
5863 {
5864 n = buf_check_timestamp(buf, focus);
5865 if (didit < n)
5866 didit = n;
5867 if (n > 0 && !buf_valid(buf))
5868 {
5869 /* Autocommands have removed the buffer, start at the
5870 * first one again. */
5871 buf = firstbuf;
5872 continue;
5873 }
5874 }
5875 buf = buf->b_next;
5876 }
5877 --no_wait_return;
5878 need_check_timestamps = FALSE;
5879 if (need_wait_return && didit == 2)
5880 {
5881 /* make sure msg isn't overwritten */
5882 msg_puts((char_u *)"\n");
5883 out_flush();
5884 }
5885 }
5886 return didit;
5887}
5888
5889/*
5890 * Move all the lines from buffer "frombuf" to buffer "tobuf".
5891 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
5892 * empty.
5893 */
5894 static int
5895move_lines(frombuf, tobuf)
5896 buf_T *frombuf;
5897 buf_T *tobuf;
5898{
5899 buf_T *tbuf = curbuf;
5900 int retval = OK;
5901 linenr_T lnum;
5902 char_u *p;
5903
5904 /* Copy the lines in "frombuf" to "tobuf". */
5905 curbuf = tobuf;
5906 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
5907 {
5908 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
5909 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
5910 {
5911 vim_free(p);
5912 retval = FAIL;
5913 break;
5914 }
5915 vim_free(p);
5916 }
5917
5918 /* Delete all the lines in "frombuf". */
5919 if (retval != FAIL)
5920 {
5921 curbuf = frombuf;
5922 while (!bufempty())
5923 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
5924 {
5925 /* Oops! We could try putting back the saved lines, but that
5926 * might fail again... */
5927 retval = FAIL;
5928 break;
5929 }
5930 }
5931
5932 curbuf = tbuf;
5933 return retval;
5934}
5935
5936/*
5937 * Check if buffer "buf" has been changed.
5938 * Also check if the file for a new buffer unexpectedly appeared.
5939 * return 1 if a changed buffer was found.
5940 * return 2 if a message has been displayed.
5941 * return 0 otherwise.
5942 */
5943/*ARGSUSED*/
5944 int
5945buf_check_timestamp(buf, focus)
5946 buf_T *buf;
5947 int focus; /* called for GUI focus event */
5948{
5949 struct stat st;
5950 int stat_res;
5951 int retval = 0;
5952 char_u *path;
5953 char_u *tbuf;
5954 char *mesg = NULL;
Bram Moolenaar44ecf652005-03-07 23:09:59 +00005955 char *mesg2 = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00005956 int helpmesg = FALSE;
5957 int reload = FALSE;
5958#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5959 int can_reload = FALSE;
5960#endif
5961 size_t orig_size = buf->b_orig_size;
5962 int orig_mode = buf->b_orig_mode;
5963#ifdef FEAT_GUI
5964 int save_mouse_correct = need_mouse_correct;
5965#endif
5966#ifdef FEAT_AUTOCMD
5967 static int busy = FALSE;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00005968 int n;
5969 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005970#endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00005971 char *reason;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005972
5973 /* If there is no file name, the buffer is not loaded, 'buftype' is
5974 * set, we are in the middle of a save or being called recursively: ignore
5975 * this buffer. */
5976 if (buf->b_ffname == NULL
5977 || buf->b_ml.ml_mfp == NULL
5978#if defined(FEAT_QUICKFIX)
5979 || *buf->b_p_bt != NUL
5980#endif
5981 || buf->b_saving
5982#ifdef FEAT_AUTOCMD
5983 || busy
5984#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00005985#ifdef FEAT_NETBEANS_INTG
5986 || isNetbeansBuffer(buf)
5987#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005988 )
5989 return 0;
5990
5991 if ( !(buf->b_flags & BF_NOTEDITED)
5992 && buf->b_mtime != 0
5993 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
5994 || time_differs((long)st.st_mtime, buf->b_mtime)
5995#ifdef HAVE_ST_MODE
5996 || (int)st.st_mode != buf->b_orig_mode
5997#else
5998 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
5999#endif
6000 ))
6001 {
6002 retval = 1;
6003
6004 /* set b_mtime to stop further warnings */
6005 if (stat_res < 0)
6006 {
6007 buf->b_mtime = 0;
6008 buf->b_orig_size = 0;
6009 buf->b_orig_mode = 0;
6010 }
6011 else
6012 buf_store_time(buf, &st, buf->b_ffname);
6013
6014 /* Don't do anything for a directory. Might contain the file
6015 * explorer. */
6016 if (mch_isdir(buf->b_fname))
6017 ;
6018
6019 /*
6020 * If 'autoread' is set, the buffer has no changes and the file still
6021 * exists, reload the buffer. Use the buffer-local option value if it
6022 * was set, the global option value otherwise.
6023 */
6024 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
6025 && !bufIsChanged(buf) && stat_res >= 0)
6026 reload = TRUE;
6027 else
6028 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006029 if (stat_res < 0)
6030 reason = "deleted";
6031 else if (bufIsChanged(buf))
6032 reason = "conflict";
6033 else if (orig_size != buf->b_orig_size || buf_contents_changed(buf))
6034 reason = "changed";
6035 else if (orig_mode != buf->b_orig_mode)
6036 reason = "mode";
6037 else
6038 reason = "time";
Bram Moolenaar071d4272004-06-13 20:20:40 +00006039
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006040#ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041 /*
6042 * Only give the warning if there are no FileChangedShell
6043 * autocommands.
6044 * Avoid being called recursively by setting "busy".
6045 */
6046 busy = TRUE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00006047# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006048 set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
6049 set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
Bram Moolenaar1e015462005-09-25 22:16:38 +00006050# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006051 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
6052 buf->b_fname, buf->b_fname, FALSE, buf);
6053 busy = FALSE;
6054 if (n)
6055 {
6056 if (!buf_valid(buf))
6057 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
Bram Moolenaar1e015462005-09-25 22:16:38 +00006058# ifdef FEAT_EVAL
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006059 s = get_vim_var_str(VV_FCS_CHOICE);
6060 if (STRCMP(s, "reload") == 0 && *reason != 'd')
6061 reload = TRUE;
6062 else if (STRCMP(s, "ask") == 0)
6063 n = FALSE;
6064 else
Bram Moolenaar1e015462005-09-25 22:16:38 +00006065# endif
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006066 return 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006067 }
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006068 if (!n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069#endif
6070 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006071 if (*reason == 'd')
6072 mesg = _("E211: File \"%s\" no longer available");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006073 else
6074 {
6075 helpmesg = TRUE;
6076#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6077 can_reload = TRUE;
6078#endif
6079 /*
6080 * Check if the file contents really changed to avoid
6081 * giving a warning when only the timestamp was set (e.g.,
6082 * checked out of CVS). Always warn when the buffer was
6083 * changed.
6084 */
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006085 if (reason[2] == 'n')
6086 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006087 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006088 mesg2 = _("See \":help W12\" for more info.");
6089 }
6090 else if (reason[1] == 'h')
6091 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006092 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006093 mesg2 = _("See \":help W11\" for more info.");
6094 }
6095 else if (*reason == 'm')
6096 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00006097 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006098 mesg2 = _("See \":help W16\" for more info.");
6099 }
6100 /* Else: only timestamp changed, ignored */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006101 }
6102 }
6103 }
6104
6105 }
6106 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6107 && vim_fexists(buf->b_ffname))
6108 {
6109 retval = 1;
6110 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6111 buf->b_flags |= BF_NEW_W;
6112#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6113 can_reload = TRUE;
6114#endif
6115 }
6116
6117 if (mesg != NULL)
6118 {
6119 path = home_replace_save(buf, buf->b_fname);
6120 if (path != NULL)
6121 {
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006122 if (!helpmesg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006123 mesg2 = "";
6124 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6125 + STRLEN(mesg2) + 2));
6126 sprintf((char *)tbuf, mesg, path);
6127#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6128 if (can_reload)
6129 {
6130 if (*mesg2 != NUL)
6131 {
6132 STRCAT(tbuf, "\n");
6133 STRCAT(tbuf, mesg2);
6134 }
6135 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6136 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6137 reload = TRUE;
6138 }
6139 else
6140#endif
6141 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6142 {
6143 if (*mesg2 != NUL)
6144 {
6145 STRCAT(tbuf, "; ");
6146 STRCAT(tbuf, mesg2);
6147 }
6148 EMSG(tbuf);
6149 retval = 2;
6150 }
6151 else
6152 {
Bram Moolenaared203462004-06-16 11:19:22 +00006153# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006154 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006155# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006156 {
6157 msg_start();
6158 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6159 if (*mesg2 != NUL)
6160 msg_puts_attr((char_u *)mesg2,
6161 hl_attr(HLF_W) + MSG_HIST);
6162 msg_clr_eos();
6163 (void)msg_end();
6164 if (emsg_silent == 0)
6165 {
6166 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006167# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006168 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006169# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006170 /* give the user some time to think about it */
6171 ui_delay(1000L, TRUE);
6172
6173 /* don't redraw and erase the message */
6174 redraw_cmdline = FALSE;
6175 }
6176 }
6177 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006178 }
6179
6180 vim_free(path);
6181 vim_free(tbuf);
6182 }
6183 }
6184
6185 if (reload)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006186 /* Reload the buffer. */
6187 buf_reload(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006188
6189#ifdef FEAT_GUI
6190 /* restore this in case an autocommand has set it; it would break
6191 * 'mousefocus' */
6192 need_mouse_correct = save_mouse_correct;
6193#endif
6194
6195 return retval;
6196}
6197
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006198/*
6199 * Reload a buffer that is already loaded.
6200 * Used when the file was changed outside of Vim.
6201 */
6202 void
6203buf_reload(buf)
6204 buf_T *buf;
6205{
6206 exarg_T ea;
6207 pos_T old_cursor;
6208 linenr_T old_topline;
6209 int old_ro = buf->b_p_ro;
6210 int orig_mode = buf->b_orig_mode;
6211 buf_T *savebuf;
6212 int saved = OK;
6213#ifdef FEAT_AUTOCMD
6214 aco_save_T aco;
6215
6216 /* set curwin/curbuf for "buf" and save some things */
6217 aucmd_prepbuf(&aco, buf);
6218#else
6219 buf_T *save_curbuf = curbuf;
6220
6221 curbuf = buf;
6222 curwin->w_buffer = buf;
6223#endif
6224
6225 /* We only want to read the text from the file, not reset the syntax
6226 * highlighting, clear marks, diff status, etc. Force the fileformat
6227 * and encoding to be the same. */
6228 if (prep_exarg(&ea, buf) == OK)
6229 {
6230 old_cursor = curwin->w_cursor;
6231 old_topline = curwin->w_topline;
6232
6233 /*
6234 * To behave like when a new file is edited (matters for
6235 * BufReadPost autocommands) we first need to delete the current
6236 * buffer contents. But if reading the file fails we should keep
6237 * the old contents. Can't use memory only, the file might be
6238 * too big. Use a hidden buffer to move the buffer contents to.
6239 */
6240 if (bufempty())
6241 savebuf = NULL;
6242 else
6243 {
6244 /* Allocate a buffer without putting it in the buffer list. */
6245 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
6246 if (savebuf != NULL)
6247 {
6248 /* Open the memline. */
6249 curbuf = savebuf;
6250 curwin->w_buffer = savebuf;
6251 saved = ml_open();
6252 curbuf = buf;
6253 curwin->w_buffer = buf;
6254 }
6255 if (savebuf == NULL || saved == FAIL
6256 || move_lines(buf, savebuf) == FAIL)
6257 {
6258 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6259 buf->b_fname);
6260 saved = FAIL;
6261 }
6262 }
6263
6264 if (saved == OK)
6265 {
6266 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6267#ifdef FEAT_AUTOCMD
6268 keep_filetype = TRUE; /* don't detect 'filetype' */
6269#endif
6270 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6271 (linenr_T)0,
6272 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6273 {
6274#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6275 if (!aborting())
6276#endif
6277 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
6278 if (savebuf != NULL)
6279 {
6280 /* Put the text back from the save buffer. First
6281 * delete any lines that readfile() added. */
6282 while (!bufempty())
6283 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
6284 == FAIL)
6285 break;
6286 (void)move_lines(savebuf, buf);
6287 }
6288 }
6289 else
6290 {
6291 /* Mark the buffer as unmodified and free undo info. */
6292 unchanged(buf, TRUE);
6293 u_blockfree(buf);
6294 u_clearall(buf);
6295 }
6296 }
6297 vim_free(ea.cmd);
6298
6299 if (savebuf != NULL)
6300 wipe_buffer(savebuf, FALSE);
6301
6302#ifdef FEAT_DIFF
6303 /* Invalidate diff info if necessary. */
6304 diff_invalidate();
6305#endif
6306
6307 /* Restore the topline and cursor position and check it (lines may
6308 * have been removed). */
6309 if (old_topline > curbuf->b_ml.ml_line_count)
6310 curwin->w_topline = curbuf->b_ml.ml_line_count;
6311 else
6312 curwin->w_topline = old_topline;
6313 curwin->w_cursor = old_cursor;
6314 check_cursor();
6315 update_topline();
6316#ifdef FEAT_AUTOCMD
6317 keep_filetype = FALSE;
6318#endif
6319#ifdef FEAT_FOLDING
6320 {
6321 win_T *wp;
6322
6323 /* Update folds unless they are defined manually. */
6324 FOR_ALL_WINDOWS(wp)
6325 if (wp->w_buffer == curwin->w_buffer
6326 && !foldmethodIsManual(wp))
6327 foldUpdateAll(wp);
6328 }
6329#endif
6330 /* If the mode didn't change and 'readonly' was set, keep the old
6331 * value; the user probably used the ":view" command. But don't
6332 * reset it, might have had a read error. */
6333 if (orig_mode == curbuf->b_orig_mode)
6334 curbuf->b_p_ro |= old_ro;
6335 }
6336
6337#ifdef FEAT_AUTOCMD
6338 /* restore curwin/curbuf and a few other things */
6339 aucmd_restbuf(&aco);
6340 /* Careful: autocommands may have made "buf" invalid! */
6341#else
6342 curwin->w_buffer = save_curbuf;
6343 curbuf = save_curbuf;
6344#endif
6345}
6346
Bram Moolenaar071d4272004-06-13 20:20:40 +00006347/*ARGSUSED*/
6348 void
6349buf_store_time(buf, st, fname)
6350 buf_T *buf;
6351 struct stat *st;
6352 char_u *fname;
6353{
6354 buf->b_mtime = (long)st->st_mtime;
6355 buf->b_orig_size = (size_t)st->st_size;
6356#ifdef HAVE_ST_MODE
6357 buf->b_orig_mode = (int)st->st_mode;
6358#else
6359 buf->b_orig_mode = mch_getperm(fname);
6360#endif
6361}
6362
6363/*
6364 * Adjust the line with missing eol, used for the next write.
6365 * Used for do_filter(), when the input lines for the filter are deleted.
6366 */
6367 void
6368write_lnum_adjust(offset)
6369 linenr_T offset;
6370{
Bram Moolenaardf177f62005-02-22 08:39:57 +00006371 if (write_no_eol_lnum != 0) /* only if there is a missing eol */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006372 write_no_eol_lnum += offset;
6373}
6374
6375#if defined(TEMPDIRNAMES) || defined(PROTO)
6376static long temp_count = 0; /* Temp filename counter. */
6377
6378/*
6379 * Delete the temp directory and all files it contains.
6380 */
6381 void
6382vim_deltempdir()
6383{
6384 char_u **files;
6385 int file_count;
6386 int i;
6387
6388 if (vim_tempdir != NULL)
6389 {
6390 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6391 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6392 EW_DIR|EW_FILE|EW_SILENT) == OK)
6393 {
6394 for (i = 0; i < file_count; ++i)
6395 mch_remove(files[i]);
6396 FreeWild(file_count, files);
6397 }
6398 gettail(NameBuff)[-1] = NUL;
6399 (void)mch_rmdir(NameBuff);
6400
6401 vim_free(vim_tempdir);
6402 vim_tempdir = NULL;
6403 }
6404}
6405#endif
6406
6407/*
6408 * vim_tempname(): Return a unique name that can be used for a temp file.
6409 *
6410 * The temp file is NOT created.
6411 *
6412 * The returned pointer is to allocated memory.
6413 * The returned pointer is NULL if no valid name was found.
6414 */
6415/*ARGSUSED*/
6416 char_u *
6417vim_tempname(extra_char)
6418 int extra_char; /* character to use in the name instead of '?' */
6419{
6420#ifdef USE_TMPNAM
6421 char_u itmp[L_tmpnam]; /* use tmpnam() */
6422#else
6423 char_u itmp[TEMPNAMELEN];
6424#endif
6425
6426#ifdef TEMPDIRNAMES
6427 static char *(tempdirs[]) = {TEMPDIRNAMES};
6428 int i;
6429 long nr;
6430 long off;
6431# ifndef EEXIST
6432 struct stat st;
6433# endif
6434
6435 /*
6436 * This will create a directory for private use by this instance of Vim.
6437 * This is done once, and the same directory is used for all temp files.
6438 * This method avoids security problems because of symlink attacks et al.
6439 * It's also a bit faster, because we only need to check for an existing
6440 * file when creating the directory and not for each temp file.
6441 */
6442 if (vim_tempdir == NULL)
6443 {
6444 /*
6445 * Try the entries in TEMPDIRNAMES to create the temp directory.
6446 */
6447 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6448 {
6449 /* expand $TMP, leave room for "/v1100000/999999999" */
6450 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6451 if (mch_isdir(itmp)) /* directory exists */
6452 {
6453# ifdef __EMX__
6454 /* If $TMP contains a forward slash (perhaps using bash or
6455 * tcsh), don't add a backslash, use a forward slash!
6456 * Adding 2 backslashes didn't work. */
6457 if (vim_strchr(itmp, '/') != NULL)
6458 STRCAT(itmp, "/");
6459 else
6460# endif
6461 add_pathsep(itmp);
6462
6463 /* Get an arbitrary number of up to 6 digits. When it's
6464 * unlikely that it already exists it will be faster,
6465 * otherwise it doesn't matter. The use of mkdir() avoids any
6466 * security problems because of the predictable number. */
6467 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6468
6469 /* Try up to 10000 different values until we find a name that
6470 * doesn't exist. */
6471 for (off = 0; off < 10000L; ++off)
6472 {
6473 int r;
6474#if defined(UNIX) || defined(VMS)
6475 mode_t umask_save;
6476#endif
6477
6478 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6479# ifndef EEXIST
6480 /* If mkdir() does not set errno to EEXIST, check for
6481 * existing file here. There is a race condition then,
6482 * although it's fail-safe. */
6483 if (mch_stat((char *)itmp, &st) >= 0)
6484 continue;
6485# endif
6486#if defined(UNIX) || defined(VMS)
6487 /* Make sure the umask doesn't remove the executable bit.
6488 * "repl" has been reported to use "177". */
6489 umask_save = umask(077);
6490#endif
6491 r = vim_mkdir(itmp, 0700);
6492#if defined(UNIX) || defined(VMS)
6493 (void)umask(umask_save);
6494#endif
6495 if (r == 0)
6496 {
6497 char_u *buf;
6498
6499 /* Directory was created, use this name.
6500 * Expand to full path; When using the current
6501 * directory a ":cd" would confuse us. */
6502 buf = alloc((unsigned)MAXPATHL + 1);
6503 if (buf != NULL)
6504 {
6505 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6506 == FAIL)
6507 STRCPY(buf, itmp);
6508# ifdef __EMX__
6509 if (vim_strchr(buf, '/') != NULL)
6510 STRCAT(buf, "/");
6511 else
6512# endif
6513 add_pathsep(buf);
6514 vim_tempdir = vim_strsave(buf);
6515 vim_free(buf);
6516 }
6517 break;
6518 }
6519# ifdef EEXIST
6520 /* If the mkdir() didn't fail because the file/dir exists,
6521 * we probably can't create any dir here, try another
6522 * place. */
6523 if (errno != EEXIST)
6524# endif
6525 break;
6526 }
6527 if (vim_tempdir != NULL)
6528 break;
6529 }
6530 }
6531 }
6532
6533 if (vim_tempdir != NULL)
6534 {
6535 /* There is no need to check if the file exists, because we own the
6536 * directory and nobody else creates a file in it. */
6537 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6538 return vim_strsave(itmp);
6539 }
6540
6541 return NULL;
6542
6543#else /* TEMPDIRNAMES */
6544
6545# ifdef WIN3264
6546 char szTempFile[_MAX_PATH + 1];
6547 char buf4[4];
6548 char_u *retval;
6549 char_u *p;
6550
6551 STRCPY(itmp, "");
6552 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6553 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6554 strcpy(buf4, "VIM");
6555 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6556 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6557 return NULL;
6558 /* GetTempFileName() will create the file, we don't want that */
6559 (void)DeleteFile(itmp);
6560
6561 /* Backslashes in a temp file name cause problems when filtering with
6562 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6563 * didn't set 'shellslash'. */
6564 retval = vim_strsave(itmp);
6565 if (*p_shcf == '-' || p_ssl)
6566 for (p = retval; *p; ++p)
6567 if (*p == '\\')
6568 *p = '/';
6569 return retval;
6570
6571# else /* WIN3264 */
6572
6573# ifdef USE_TMPNAM
6574 /* tmpnam() will make its own name */
6575 if (*tmpnam((char *)itmp) == NUL)
6576 return NULL;
6577# else
6578 char_u *p;
6579
6580# ifdef VMS_TEMPNAM
6581 /* mktemp() is not working on VMS. It seems to be
6582 * a do-nothing function. Therefore we use tempnam().
6583 */
6584 sprintf((char *)itmp, "VIM%c", extra_char);
6585 p = (char_u *)tempnam("tmp:", (char *)itmp);
6586 if (p != NULL)
6587 {
6588 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6589 * and VIM will then be unable to find the file later */
6590 STRCPY(itmp, p);
6591 STRCAT(itmp, ".txt");
6592 free(p);
6593 }
6594 else
6595 return NULL;
6596# else
6597 STRCPY(itmp, TEMPNAME);
6598 if ((p = vim_strchr(itmp, '?')) != NULL)
6599 *p = extra_char;
6600 if (mktemp((char *)itmp) == NULL)
6601 return NULL;
6602# endif
6603# endif
6604
6605 return vim_strsave(itmp);
6606# endif /* WIN3264 */
6607#endif /* TEMPDIRNAMES */
6608}
6609
6610#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6611/*
6612 * Convert all backslashes in fname to forward slashes in-place.
6613 */
6614 void
6615forward_slash(fname)
6616 char_u *fname;
6617{
6618 char_u *p;
6619
6620 for (p = fname; *p != NUL; ++p)
6621# ifdef FEAT_MBYTE
6622 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00006623 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006624 ++p;
6625 else
6626# endif
6627 if (*p == '\\')
6628 *p = '/';
6629}
6630#endif
6631
6632
6633/*
6634 * Code for automatic commands.
6635 *
6636 * Only included when "FEAT_AUTOCMD" has been defined.
6637 */
6638
6639#if defined(FEAT_AUTOCMD) || defined(PROTO)
6640
6641/*
6642 * The autocommands are stored in a list for each event.
6643 * Autocommands for the same pattern, that are consecutive, are joined
6644 * together, to avoid having to match the pattern too often.
6645 * The result is an array of Autopat lists, which point to AutoCmd lists:
6646 *
6647 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6648 * Autopat.cmds Autopat.cmds
6649 * | |
6650 * V V
6651 * AutoCmd.next AutoCmd.next
6652 * | |
6653 * V V
6654 * AutoCmd.next NULL
6655 * |
6656 * V
6657 * NULL
6658 *
6659 * first_autopat[1] --> Autopat.next --> NULL
6660 * Autopat.cmds
6661 * |
6662 * V
6663 * AutoCmd.next
6664 * |
6665 * V
6666 * NULL
6667 * etc.
6668 *
6669 * The order of AutoCmds is important, this is the order in which they were
6670 * defined and will have to be executed.
6671 */
6672typedef struct AutoCmd
6673{
6674 char_u *cmd; /* The command to be executed (NULL
6675 when command has been removed) */
6676 char nested; /* If autocommands nest here */
6677 char last; /* last command in list */
6678#ifdef FEAT_EVAL
6679 scid_T scriptID; /* script ID where defined */
6680#endif
6681 struct AutoCmd *next; /* Next AutoCmd in list */
6682} AutoCmd;
6683
6684typedef struct AutoPat
6685{
6686 int group; /* group ID */
6687 char_u *pat; /* pattern as typed (NULL when pattern
6688 has been removed) */
6689 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00006690 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006691 char allow_dirs; /* Pattern may match whole path */
6692 char last; /* last pattern for apply_autocmds() */
6693 AutoCmd *cmds; /* list of commands to do */
6694 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006695 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696} AutoPat;
6697
6698static struct event_name
6699{
6700 char *name; /* event name */
6701 EVENT_T event; /* event number */
6702} event_names[] =
6703{
6704 {"BufAdd", EVENT_BUFADD},
6705 {"BufCreate", EVENT_BUFADD},
6706 {"BufDelete", EVENT_BUFDELETE},
6707 {"BufEnter", EVENT_BUFENTER},
6708 {"BufFilePost", EVENT_BUFFILEPOST},
6709 {"BufFilePre", EVENT_BUFFILEPRE},
6710 {"BufHidden", EVENT_BUFHIDDEN},
6711 {"BufLeave", EVENT_BUFLEAVE},
6712 {"BufNew", EVENT_BUFNEW},
6713 {"BufNewFile", EVENT_BUFNEWFILE},
6714 {"BufRead", EVENT_BUFREADPOST},
6715 {"BufReadCmd", EVENT_BUFREADCMD},
6716 {"BufReadPost", EVENT_BUFREADPOST},
6717 {"BufReadPre", EVENT_BUFREADPRE},
6718 {"BufUnload", EVENT_BUFUNLOAD},
6719 {"BufWinEnter", EVENT_BUFWINENTER},
6720 {"BufWinLeave", EVENT_BUFWINLEAVE},
6721 {"BufWipeout", EVENT_BUFWIPEOUT},
6722 {"BufWrite", EVENT_BUFWRITEPRE},
6723 {"BufWritePost", EVENT_BUFWRITEPOST},
6724 {"BufWritePre", EVENT_BUFWRITEPRE},
6725 {"BufWriteCmd", EVENT_BUFWRITECMD},
6726 {"CmdwinEnter", EVENT_CMDWINENTER},
6727 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006728 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006729 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6730 {"FileEncoding", EVENT_ENCODINGCHANGED},
6731 {"CursorHold", EVENT_CURSORHOLD},
6732 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6733 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6734 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6735 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
6736 {"FileChangedRO", EVENT_FILECHANGEDRO},
6737 {"FileReadPost", EVENT_FILEREADPOST},
6738 {"FileReadPre", EVENT_FILEREADPRE},
6739 {"FileReadCmd", EVENT_FILEREADCMD},
6740 {"FileType", EVENT_FILETYPE},
6741 {"FileWritePost", EVENT_FILEWRITEPOST},
6742 {"FileWritePre", EVENT_FILEWRITEPRE},
6743 {"FileWriteCmd", EVENT_FILEWRITECMD},
6744 {"FilterReadPost", EVENT_FILTERREADPOST},
6745 {"FilterReadPre", EVENT_FILTERREADPRE},
6746 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6747 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6748 {"FocusGained", EVENT_FOCUSGAINED},
6749 {"FocusLost", EVENT_FOCUSLOST},
6750 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6751 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006752 {"InsertChange", EVENT_INSERTCHANGE},
6753 {"InsertEnter", EVENT_INSERTENTER},
6754 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00006755 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00006756 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
6757 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006758 {"RemoteReply", EVENT_REMOTEREPLY},
6759 {"StdinReadPost", EVENT_STDINREADPOST},
6760 {"StdinReadPre", EVENT_STDINREADPRE},
6761 {"Syntax", EVENT_SYNTAX},
6762 {"TermChanged", EVENT_TERMCHANGED},
6763 {"TermResponse", EVENT_TERMRESPONSE},
6764 {"User", EVENT_USER},
6765 {"VimEnter", EVENT_VIMENTER},
6766 {"VimLeave", EVENT_VIMLEAVE},
6767 {"VimLeavePre", EVENT_VIMLEAVEPRE},
6768 {"WinEnter", EVENT_WINENTER},
6769 {"WinLeave", EVENT_WINLEAVE},
6770 {NULL, (EVENT_T)0}
6771};
6772
6773static AutoPat *first_autopat[NUM_EVENTS] =
6774{
6775 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6776 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6777 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6778 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006779 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6780 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006781};
6782
6783/*
6784 * struct used to keep status while executing autocommands for an event.
6785 */
6786typedef struct AutoPatCmd
6787{
6788 AutoPat *curpat; /* next AutoPat to examine */
6789 AutoCmd *nextcmd; /* next AutoCmd to execute */
6790 int group; /* group being used */
6791 char_u *fname; /* fname to match with */
6792 char_u *sfname; /* sfname to match with */
6793 char_u *tail; /* tail of fname */
6794 EVENT_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006795 int arg_bufnr; /* initially equal to <abuf>, set to zero when
6796 buf is deleted */
6797 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006798} AutoPatCmd;
6799
Bram Moolenaard6f676d2005-06-01 21:51:55 +00006800static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006801
Bram Moolenaar071d4272004-06-13 20:20:40 +00006802/*
6803 * augroups stores a list of autocmd group names.
6804 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00006805static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00006806#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
6807
6808/*
6809 * The ID of the current group. Group 0 is the default one.
6810 */
6811#define AUGROUP_DEFAULT -1 /* default autocmd group */
6812#define AUGROUP_ERROR -2 /* errornouse autocmd group */
6813#define AUGROUP_ALL -3 /* all autocmd groups */
6814static int current_augroup = AUGROUP_DEFAULT;
6815
6816static int au_need_clean = FALSE; /* need to delete marked patterns */
6817
6818static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
6819static void au_remove_pat __ARGS((AutoPat *ap));
6820static void au_remove_cmds __ARGS((AutoPat *ap));
6821static void au_cleanup __ARGS((void));
6822static int au_new_group __ARGS((char_u *name));
6823static void au_del_group __ARGS((char_u *name));
6824static int au_find_group __ARGS((char_u *name));
6825static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
6826static char_u *event_nr2name __ARGS((EVENT_T event));
6827static char_u *find_end_event __ARGS((char_u *arg, int have_group));
6828static int event_ignored __ARGS((EVENT_T event));
6829static int au_get_grouparg __ARGS((char_u **argp));
6830static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
6831static char_u *getnextac __ARGS((int c, void *cookie, int indent));
6832static 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));
6833static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
6834
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006835
Bram Moolenaar071d4272004-06-13 20:20:40 +00006836static EVENT_T last_event;
6837static int last_group;
6838
6839/*
6840 * Show the autocommands for one AutoPat.
6841 */
6842 static void
6843show_autocmd(ap, event)
6844 AutoPat *ap;
6845 EVENT_T event;
6846{
6847 AutoCmd *ac;
6848
6849 /* Check for "got_int" (here and at various places below), which is set
6850 * when "q" has been hit for the "--more--" prompt */
6851 if (got_int)
6852 return;
6853 if (ap->pat == NULL) /* pattern has been removed */
6854 return;
6855
6856 msg_putchar('\n');
6857 if (got_int)
6858 return;
6859 if (event != last_event || ap->group != last_group)
6860 {
6861 if (ap->group != AUGROUP_DEFAULT)
6862 {
6863 if (AUGROUP_NAME(ap->group) == NULL)
6864 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
6865 else
6866 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
6867 msg_puts((char_u *)" ");
6868 }
6869 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
6870 last_event = event;
6871 last_group = ap->group;
6872 msg_putchar('\n');
6873 if (got_int)
6874 return;
6875 }
6876 msg_col = 4;
6877 msg_outtrans(ap->pat);
6878
6879 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6880 {
6881 if (ac->cmd != NULL) /* skip removed commands */
6882 {
6883 if (msg_col >= 14)
6884 msg_putchar('\n');
6885 msg_col = 14;
6886 if (got_int)
6887 return;
6888 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00006889#ifdef FEAT_EVAL
6890 if (p_verbose > 0)
6891 last_set_msg(ac->scriptID);
6892#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006893 if (got_int)
6894 return;
6895 if (ac->next != NULL)
6896 {
6897 msg_putchar('\n');
6898 if (got_int)
6899 return;
6900 }
6901 }
6902 }
6903}
6904
6905/*
6906 * Mark an autocommand pattern for deletion.
6907 */
6908 static void
6909au_remove_pat(ap)
6910 AutoPat *ap;
6911{
6912 vim_free(ap->pat);
6913 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006914 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006915 au_need_clean = TRUE;
6916}
6917
6918/*
6919 * Mark all commands for a pattern for deletion.
6920 */
6921 static void
6922au_remove_cmds(ap)
6923 AutoPat *ap;
6924{
6925 AutoCmd *ac;
6926
6927 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6928 {
6929 vim_free(ac->cmd);
6930 ac->cmd = NULL;
6931 }
6932 au_need_clean = TRUE;
6933}
6934
6935/*
6936 * Cleanup autocommands and patterns that have been deleted.
6937 * This is only done when not executing autocommands.
6938 */
6939 static void
6940au_cleanup()
6941{
6942 AutoPat *ap, **prev_ap;
6943 AutoCmd *ac, **prev_ac;
6944 EVENT_T event;
6945
6946 if (autocmd_busy || !au_need_clean)
6947 return;
6948
6949 /* loop over all events */
6950 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
6951 event = (EVENT_T)((int)event + 1))
6952 {
6953 /* loop over all autocommand patterns */
6954 prev_ap = &(first_autopat[(int)event]);
6955 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
6956 {
6957 /* loop over all commands for this pattern */
6958 prev_ac = &(ap->cmds);
6959 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
6960 {
6961 /* remove the command if the pattern is to be deleted or when
6962 * the command has been marked for deletion */
6963 if (ap->pat == NULL || ac->cmd == NULL)
6964 {
6965 *prev_ac = ac->next;
6966 vim_free(ac->cmd);
6967 vim_free(ac);
6968 }
6969 else
6970 prev_ac = &(ac->next);
6971 }
6972
6973 /* remove the pattern if it has been marked for deletion */
6974 if (ap->pat == NULL)
6975 {
6976 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00006977 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006978 vim_free(ap);
6979 }
6980 else
6981 prev_ap = &(ap->next);
6982 }
6983 }
6984
6985 au_need_clean = FALSE;
6986}
6987
6988/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006989 * Called when buffer is freed, to remove/invalidate related buffer-local
6990 * autocmds.
6991 */
6992 void
6993aubuflocal_remove(buf)
6994 buf_T *buf;
6995{
6996 AutoPat *ap;
6997 EVENT_T event;
6998 AutoPatCmd *apc;
6999
7000 /* invalidate currently executing autocommands */
7001 for (apc = active_apc_list; apc; apc = apc->next)
7002 if (buf->b_fnum == apc->arg_bufnr)
7003 apc->arg_bufnr = 0;
7004
7005 /* invalidate buflocals looping through events */
7006 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7007 event = (EVENT_T)((int)event + 1))
7008 /* loop over all autocommand patterns */
7009 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7010 if (ap->buflocal_nr == buf->b_fnum)
7011 {
7012 au_remove_pat(ap);
7013 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007014 {
7015 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007016 smsg((char_u *)
7017 _("auto-removing autocommand: %s <buffer=%d>"),
7018 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007019 verbose_leave();
7020 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007021 }
7022 au_cleanup();
7023}
7024
7025/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007026 * Add an autocmd group name.
7027 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7028 */
7029 static int
7030au_new_group(name)
7031 char_u *name;
7032{
7033 int i;
7034
7035 i = au_find_group(name);
7036 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
7037 {
7038 /* First try using a free entry. */
7039 for (i = 0; i < augroups.ga_len; ++i)
7040 if (AUGROUP_NAME(i) == NULL)
7041 break;
7042 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
7043 return AUGROUP_ERROR;
7044
7045 AUGROUP_NAME(i) = vim_strsave(name);
7046 if (AUGROUP_NAME(i) == NULL)
7047 return AUGROUP_ERROR;
7048 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007049 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007050 }
7051
7052 return i;
7053}
7054
7055 static void
7056au_del_group(name)
7057 char_u *name;
7058{
7059 int i;
7060
7061 i = au_find_group(name);
7062 if (i == AUGROUP_ERROR) /* the group doesn't exist */
7063 EMSG2(_("E367: No such group: \"%s\""), name);
7064 else
7065 {
7066 vim_free(AUGROUP_NAME(i));
7067 AUGROUP_NAME(i) = NULL;
7068 }
7069}
7070
7071/*
7072 * Find the ID of an autocmd group name.
7073 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7074 */
7075 static int
7076au_find_group(name)
7077 char_u *name;
7078{
7079 int i;
7080
7081 for (i = 0; i < augroups.ga_len; ++i)
7082 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
7083 return i;
7084 return AUGROUP_ERROR;
7085}
7086
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007087#if defined(FEAT_BROWSE) || defined(PROTO)
7088/*
7089 * Return TRUE if augroup "name" exists.
7090 */
7091 int
7092au_has_group(name)
7093 char_u *name;
7094{
7095 return au_find_group(name) != AUGROUP_ERROR;
7096}
7097#endif
7098
Bram Moolenaar071d4272004-06-13 20:20:40 +00007099/*
7100 * ":augroup {name}".
7101 */
7102 void
7103do_augroup(arg, del_group)
7104 char_u *arg;
7105 int del_group;
7106{
7107 int i;
7108
7109 if (del_group)
7110 {
7111 if (*arg == NUL)
7112 EMSG(_(e_argreq));
7113 else
7114 au_del_group(arg);
7115 }
7116 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
7117 current_augroup = AUGROUP_DEFAULT;
7118 else if (*arg) /* ":aug xxx": switch to group xxx */
7119 {
7120 i = au_new_group(arg);
7121 if (i != AUGROUP_ERROR)
7122 current_augroup = i;
7123 }
7124 else /* ":aug": list the group names */
7125 {
7126 msg_start();
7127 for (i = 0; i < augroups.ga_len; ++i)
7128 {
7129 if (AUGROUP_NAME(i) != NULL)
7130 {
7131 msg_puts(AUGROUP_NAME(i));
7132 msg_puts((char_u *)" ");
7133 }
7134 }
7135 msg_clr_eos();
7136 msg_end();
7137 }
7138}
7139
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007140#if defined(EXITFREE) || defined(PROTO)
7141 void
7142free_all_autocmds()
7143{
7144 for (current_augroup = -1; current_augroup < augroups.ga_len;
7145 ++current_augroup)
7146 do_autocmd((char_u *)"", TRUE);
7147 ga_clear_strings(&augroups);
7148}
7149#endif
7150
Bram Moolenaar071d4272004-06-13 20:20:40 +00007151/*
7152 * Return the event number for event name "start".
7153 * Return NUM_EVENTS if the event name was not found.
7154 * Return a pointer to the next event name in "end".
7155 */
7156 static EVENT_T
7157event_name2nr(start, end)
7158 char_u *start;
7159 char_u **end;
7160{
7161 char_u *p;
7162 int i;
7163 int len;
7164
7165 /* the event name ends with end of line, a blank or a comma */
7166 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7167 ;
7168 for (i = 0; event_names[i].name != NULL; ++i)
7169 {
7170 len = (int)STRLEN(event_names[i].name);
7171 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7172 break;
7173 }
7174 if (*p == ',')
7175 ++p;
7176 *end = p;
7177 if (event_names[i].name == NULL)
7178 return NUM_EVENTS;
7179 return event_names[i].event;
7180}
7181
7182/*
7183 * Return the name for event "event".
7184 */
7185 static char_u *
7186event_nr2name(event)
7187 EVENT_T event;
7188{
7189 int i;
7190
7191 for (i = 0; event_names[i].name != NULL; ++i)
7192 if (event_names[i].event == event)
7193 return (char_u *)event_names[i].name;
7194 return (char_u *)"Unknown";
7195}
7196
7197/*
7198 * Scan over the events. "*" stands for all events.
7199 */
7200 static char_u *
7201find_end_event(arg, have_group)
7202 char_u *arg;
7203 int have_group; /* TRUE when group name was found */
7204{
7205 char_u *pat;
7206 char_u *p;
7207
7208 if (*arg == '*')
7209 {
7210 if (arg[1] && !vim_iswhite(arg[1]))
7211 {
7212 EMSG2(_("E215: Illegal character after *: %s"), arg);
7213 return NULL;
7214 }
7215 pat = arg + 1;
7216 }
7217 else
7218 {
7219 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7220 {
7221 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7222 {
7223 if (have_group)
7224 EMSG2(_("E216: No such event: %s"), pat);
7225 else
7226 EMSG2(_("E216: No such group or event: %s"), pat);
7227 return NULL;
7228 }
7229 }
7230 }
7231 return pat;
7232}
7233
7234/*
7235 * Return TRUE if "event" is included in 'eventignore'.
7236 */
7237 static int
7238event_ignored(event)
7239 EVENT_T event;
7240{
7241 char_u *p = p_ei;
7242
7243 if (STRICMP(p_ei, "all") == 0)
7244 return TRUE;
7245
7246 while (*p)
7247 if (event_name2nr(p, &p) == event)
7248 return TRUE;
7249
7250 return FALSE;
7251}
7252
7253/*
7254 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7255 */
7256 int
7257check_ei()
7258{
7259 char_u *p = p_ei;
7260
7261 if (STRICMP(p_ei, "all") == 0)
7262 return OK;
7263
7264 while (*p)
7265 if (event_name2nr(p, &p) == NUM_EVENTS)
7266 return FAIL;
7267
7268 return OK;
7269}
7270
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007271# if defined(FEAT_SYN_HL) || defined(PROTO)
7272
7273/*
7274 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7275 * buffer loaded into the window. "what" must start with a comma.
7276 * Returns the old value of 'eventignore' in allocated memory.
7277 */
7278 char_u *
7279au_event_disable(what)
7280 char *what;
7281{
7282 char_u *new_ei;
7283 char_u *save_ei;
7284
7285 save_ei = vim_strsave(p_ei);
7286 if (save_ei != NULL)
7287 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00007288 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007289 if (new_ei != NULL)
7290 {
7291 STRCAT(new_ei, what);
7292 set_string_option_direct((char_u *)"ei", -1, new_ei, OPT_FREE);
7293 vim_free(new_ei);
7294 }
7295 }
7296 return save_ei;
7297}
7298
7299 void
7300au_event_restore(old_ei)
7301 char_u *old_ei;
7302{
7303 if (old_ei != NULL)
7304 {
7305 set_string_option_direct((char_u *)"ei", -1, old_ei, OPT_FREE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007306 vim_free(old_ei);
7307 }
7308}
7309# endif /* FEAT_SYN_HL */
7310
Bram Moolenaar071d4272004-06-13 20:20:40 +00007311/*
7312 * do_autocmd() -- implements the :autocmd command. Can be used in the
7313 * following ways:
7314 *
7315 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7316 * will be automatically executed for <event>
7317 * when editing a file matching <pat>, in
7318 * the current group.
7319 * :autocmd <event> <pat> Show the auto-commands associated with
7320 * <event> and <pat>.
7321 * :autocmd <event> Show the auto-commands associated with
7322 * <event>.
7323 * :autocmd Show all auto-commands.
7324 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7325 * <event> and <pat>, and add the command
7326 * <cmd>, for the current group.
7327 * :autocmd! <event> <pat> Remove all auto-commands associated with
7328 * <event> and <pat> for the current group.
7329 * :autocmd! <event> Remove all auto-commands associated with
7330 * <event> for the current group.
7331 * :autocmd! Remove ALL auto-commands for the current
7332 * group.
7333 *
7334 * Multiple events and patterns may be given separated by commas. Here are
7335 * some examples:
7336 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7337 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7338 *
7339 * :autocmd * *.c show all autocommands for *.c files.
7340 */
7341 void
7342do_autocmd(arg, forceit)
7343 char_u *arg;
7344 int forceit;
7345{
7346 char_u *pat;
7347 char_u *envpat = NULL;
7348 char_u *cmd;
7349 EVENT_T event;
7350 int need_free = FALSE;
7351 int nested = FALSE;
7352 int group;
7353
7354 /*
7355 * Check for a legal group name. If not, use AUGROUP_ALL.
7356 */
7357 group = au_get_grouparg(&arg);
7358 if (arg == NULL) /* out of memory */
7359 return;
7360
7361 /*
7362 * Scan over the events.
7363 * If we find an illegal name, return here, don't do anything.
7364 */
7365 pat = find_end_event(arg, group != AUGROUP_ALL);
7366 if (pat == NULL)
7367 return;
7368
7369 /*
7370 * Scan over the pattern. Put a NUL at the end.
7371 */
7372 pat = skipwhite(pat);
7373 cmd = pat;
7374 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7375 cmd++;
7376 if (*cmd)
7377 *cmd++ = NUL;
7378
7379 /* Expand environment variables in the pattern. Set 'shellslash', we want
7380 * forward slashes here. */
7381 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7382 {
7383#ifdef BACKSLASH_IN_FILENAME
7384 int p_ssl_save = p_ssl;
7385
7386 p_ssl = TRUE;
7387#endif
7388 envpat = expand_env_save(pat);
7389#ifdef BACKSLASH_IN_FILENAME
7390 p_ssl = p_ssl_save;
7391#endif
7392 if (envpat != NULL)
7393 pat = envpat;
7394 }
7395
7396 /*
7397 * Check for "nested" flag.
7398 */
7399 cmd = skipwhite(cmd);
7400 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7401 {
7402 nested = TRUE;
7403 cmd = skipwhite(cmd + 6);
7404 }
7405
7406 /*
7407 * Find the start of the commands.
7408 * Expand <sfile> in it.
7409 */
7410 if (*cmd != NUL)
7411 {
7412 cmd = expand_sfile(cmd);
7413 if (cmd == NULL) /* some error */
7414 return;
7415 need_free = TRUE;
7416 }
7417
7418 /*
7419 * Print header when showing autocommands.
7420 */
7421 if (!forceit && *cmd == NUL)
7422 {
7423 /* Highlight title */
7424 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7425 }
7426
7427 /*
7428 * Loop over the events.
7429 */
7430 last_event = (EVENT_T)-1; /* for listing the event name */
7431 last_group = AUGROUP_ERROR; /* for listing the group name */
7432 if (*arg == '*' || *arg == NUL)
7433 {
7434 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7435 event = (EVENT_T)((int)event + 1))
7436 if (do_autocmd_event(event, pat,
7437 nested, cmd, forceit, group) == FAIL)
7438 break;
7439 }
7440 else
7441 {
7442 while (*arg && !vim_iswhite(*arg))
7443 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7444 nested, cmd, forceit, group) == FAIL)
7445 break;
7446 }
7447
7448 if (need_free)
7449 vim_free(cmd);
7450 vim_free(envpat);
7451}
7452
7453/*
7454 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7455 * The "argp" argument is advanced to the following argument.
7456 *
7457 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7458 */
7459 static int
7460au_get_grouparg(argp)
7461 char_u **argp;
7462{
7463 char_u *group_name;
7464 char_u *p;
7465 char_u *arg = *argp;
7466 int group = AUGROUP_ALL;
7467
7468 p = skiptowhite(arg);
7469 if (p > arg)
7470 {
7471 group_name = vim_strnsave(arg, (int)(p - arg));
7472 if (group_name == NULL) /* out of memory */
7473 return AUGROUP_ERROR;
7474 group = au_find_group(group_name);
7475 if (group == AUGROUP_ERROR)
7476 group = AUGROUP_ALL; /* no match, use all groups */
7477 else
7478 *argp = skipwhite(p); /* match, skip over group name */
7479 vim_free(group_name);
7480 }
7481 return group;
7482}
7483
7484/*
7485 * do_autocmd() for one event.
7486 * If *pat == NUL do for all patterns.
7487 * If *cmd == NUL show entries.
7488 * If forceit == TRUE delete entries.
7489 * If group is not AUGROUP_ALL, only use this group.
7490 */
7491 static int
7492do_autocmd_event(event, pat, nested, cmd, forceit, group)
7493 EVENT_T event;
7494 char_u *pat;
7495 int nested;
7496 char_u *cmd;
7497 int forceit;
7498 int group;
7499{
7500 AutoPat *ap;
7501 AutoPat **prev_ap;
7502 AutoCmd *ac;
7503 AutoCmd **prev_ac;
7504 int brace_level;
7505 char_u *endpat;
7506 int findgroup;
7507 int allgroups;
7508 int patlen;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007509 int is_buflocal;
7510 int buflocal_nr;
7511 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007512
7513 if (group == AUGROUP_ALL)
7514 findgroup = current_augroup;
7515 else
7516 findgroup = group;
7517 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7518
7519 /*
7520 * Show or delete all patterns for an event.
7521 */
7522 if (*pat == NUL)
7523 {
7524 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7525 {
7526 if (forceit) /* delete the AutoPat, if it's in the current group */
7527 {
7528 if (ap->group == findgroup)
7529 au_remove_pat(ap);
7530 }
7531 else if (group == AUGROUP_ALL || ap->group == group)
7532 show_autocmd(ap, event);
7533 }
7534 }
7535
7536 /*
7537 * Loop through all the specified patterns.
7538 */
7539 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7540 {
7541 /*
7542 * Find end of the pattern.
7543 * Watch out for a comma in braces, like "*.\{obj,o\}".
7544 */
7545 brace_level = 0;
7546 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7547 || endpat[-1] == '\\'); ++endpat)
7548 {
7549 if (*endpat == '{')
7550 brace_level++;
7551 else if (*endpat == '}')
7552 brace_level--;
7553 }
7554 if (pat == endpat) /* ignore single comma */
7555 continue;
7556 patlen = (int)(endpat - pat);
7557
7558 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007559 * detect special <buflocal[=X]> buffer-local patterns
7560 */
7561 is_buflocal = FALSE;
7562 buflocal_nr = 0;
7563
7564 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
7565 && pat[patlen - 1] == '>')
7566 {
7567 /* Error will be printed only for addition. printing and removing
7568 * will proceed silently. */
7569 is_buflocal = TRUE;
7570 if (patlen == 8)
7571 buflocal_nr = curbuf->b_fnum;
7572 else if (patlen > 9 && pat[7] == '=')
7573 {
7574 /* <buffer=abuf> */
7575 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
7576 buflocal_nr = autocmd_bufnr;
7577 /* <buffer=123> */
7578 else if (skipdigits(pat + 8) == pat + patlen - 1)
7579 buflocal_nr = atoi((char *)pat + 8);
7580 }
7581 }
7582
7583 if (is_buflocal)
7584 {
7585 /* normalize pat into standard "<buffer>#N" form */
7586 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
7587 pat = buflocal_pat; /* can modify pat and patlen */
7588 patlen = STRLEN(buflocal_pat); /* but not endpat */
7589 }
7590
7591 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007592 * Find AutoPat entries with this pattern.
7593 */
7594 prev_ap = &first_autopat[(int)event];
7595 while ((ap = *prev_ap) != NULL)
7596 {
7597 if (ap->pat != NULL)
7598 {
7599 /* Accept a pattern when:
7600 * - a group was specified and it's that group, or a group was
7601 * not specified and it's the current group, or a group was
7602 * not specified and we are listing
7603 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007604 * - the pattern matches.
7605 * For <buffer[=X]>, this condition works because we normalize
7606 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007607 */
7608 if ((allgroups || ap->group == findgroup)
7609 && ap->patlen == patlen
7610 && STRNCMP(pat, ap->pat, patlen) == 0)
7611 {
7612 /*
7613 * Remove existing autocommands.
7614 * If adding any new autocmd's for this AutoPat, don't
7615 * delete the pattern from the autopat list, append to
7616 * this list.
7617 */
7618 if (forceit)
7619 {
7620 if (*cmd != NUL && ap->next == NULL)
7621 {
7622 au_remove_cmds(ap);
7623 break;
7624 }
7625 au_remove_pat(ap);
7626 }
7627
7628 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007629 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00007630 */
7631 else if (*cmd == NUL)
7632 show_autocmd(ap, event);
7633
7634 /*
7635 * Add autocmd to this autopat, if it's the last one.
7636 */
7637 else if (ap->next == NULL)
7638 break;
7639 }
7640 }
7641 prev_ap = &ap->next;
7642 }
7643
7644 /*
7645 * Add a new command.
7646 */
7647 if (*cmd != NUL)
7648 {
7649 /*
7650 * If the pattern we want to add a command to does appear at the
7651 * end of the list (or not is not in the list at all), add the
7652 * pattern at the end of the list.
7653 */
7654 if (ap == NULL)
7655 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007656 /* refuse to add buffer-local ap if buffer number is invalid */
7657 if (is_buflocal && (buflocal_nr == 0
7658 || buflist_findnr(buflocal_nr) == NULL))
7659 {
7660 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
7661 buflocal_nr);
7662 return FAIL;
7663 }
7664
Bram Moolenaar071d4272004-06-13 20:20:40 +00007665 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7666 if (ap == NULL)
7667 return FAIL;
7668 ap->pat = vim_strnsave(pat, patlen);
7669 ap->patlen = patlen;
7670 if (ap->pat == NULL)
7671 {
7672 vim_free(ap);
7673 return FAIL;
7674 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007675
7676 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007677 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007678 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007679 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007680 }
7681 else
7682 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00007683 char_u *reg_pat;
7684
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007685 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007686 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007687 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007688 if (reg_pat != NULL)
7689 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007690 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007691 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007692 {
7693 vim_free(ap->pat);
7694 vim_free(ap);
7695 return FAIL;
7696 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007697 }
7698 ap->cmds = NULL;
7699 *prev_ap = ap;
7700 ap->next = NULL;
7701 if (group == AUGROUP_ALL)
7702 ap->group = current_augroup;
7703 else
7704 ap->group = group;
7705 }
7706
7707 /*
7708 * Add the autocmd at the end of the AutoCmd list.
7709 */
7710 prev_ac = &(ap->cmds);
7711 while ((ac = *prev_ac) != NULL)
7712 prev_ac = &ac->next;
7713 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7714 if (ac == NULL)
7715 return FAIL;
7716 ac->cmd = vim_strsave(cmd);
7717#ifdef FEAT_EVAL
7718 ac->scriptID = current_SID;
7719#endif
7720 if (ac->cmd == NULL)
7721 {
7722 vim_free(ac);
7723 return FAIL;
7724 }
7725 ac->next = NULL;
7726 *prev_ac = ac;
7727 ac->nested = nested;
7728 }
7729 }
7730
7731 au_cleanup(); /* may really delete removed patterns/commands now */
7732 return OK;
7733}
7734
7735/*
7736 * Implementation of ":doautocmd [group] event [fname]".
7737 * Return OK for success, FAIL for failure;
7738 */
7739 int
7740do_doautocmd(arg, do_msg)
7741 char_u *arg;
7742 int do_msg; /* give message for no matching autocmds? */
7743{
7744 char_u *fname;
7745 int nothing_done = TRUE;
7746 int group;
7747
7748 /*
7749 * Check for a legal group name. If not, use AUGROUP_ALL.
7750 */
7751 group = au_get_grouparg(&arg);
7752 if (arg == NULL) /* out of memory */
7753 return FAIL;
7754
7755 if (*arg == '*')
7756 {
7757 EMSG(_("E217: Can't execute autocommands for ALL events"));
7758 return FAIL;
7759 }
7760
7761 /*
7762 * Scan over the events.
7763 * If we find an illegal name, return here, don't do anything.
7764 */
7765 fname = find_end_event(arg, group != AUGROUP_ALL);
7766 if (fname == NULL)
7767 return FAIL;
7768
7769 fname = skipwhite(fname);
7770
7771 /*
7772 * Loop over the events.
7773 */
7774 while (*arg && !vim_iswhite(*arg))
7775 if (apply_autocmds_group(event_name2nr(arg, &arg),
7776 fname, NULL, TRUE, group, curbuf, NULL))
7777 nothing_done = FALSE;
7778
7779 if (nothing_done && do_msg)
7780 MSG(_("No matching autocommands"));
7781
7782#ifdef FEAT_EVAL
7783 return aborting() ? FAIL : OK;
7784#else
7785 return OK;
7786#endif
7787}
7788
7789/*
7790 * ":doautoall": execute autocommands for each loaded buffer.
7791 */
7792 void
7793ex_doautoall(eap)
7794 exarg_T *eap;
7795{
7796 int retval;
7797 aco_save_T aco;
7798 buf_T *buf;
7799
7800 /*
7801 * This is a bit tricky: For some commands curwin->w_buffer needs to be
7802 * equal to curbuf, but for some buffers there may not be a window.
7803 * So we change the buffer for the current window for a moment. This
7804 * gives problems when the autocommands make changes to the list of
7805 * buffers or windows...
7806 */
7807 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7808 {
7809 if (curbuf->b_ml.ml_mfp != NULL)
7810 {
7811 /* find a window for this buffer and save some values */
7812 aucmd_prepbuf(&aco, buf);
7813
7814 /* execute the autocommands for this buffer */
7815 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00007816 do_modelines(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007817
7818 /* restore the current window */
7819 aucmd_restbuf(&aco);
7820
7821 /* stop if there is some error or buffer was deleted */
7822 if (retval == FAIL || !buf_valid(buf))
7823 break;
7824 }
7825 }
7826
7827 check_cursor(); /* just in case lines got deleted */
7828}
7829
7830/*
7831 * Prepare for executing autocommands for (hidden) buffer "buf".
7832 * Search a window for the current buffer. Save the cursor position and
7833 * screen offset.
7834 * Set "curbuf" and "curwin" to match "buf".
7835 */
7836 void
7837aucmd_prepbuf(aco, buf)
7838 aco_save_T *aco; /* structure to save values in */
7839 buf_T *buf; /* new curbuf */
7840{
7841 win_T *win;
7842
7843 aco->new_curbuf = buf;
7844
7845 /* Find a window that is for the new buffer */
7846 if (buf == curbuf) /* be quick when buf is curbuf */
7847 win = curwin;
7848 else
7849#ifdef FEAT_WINDOWS
7850 for (win = firstwin; win != NULL; win = win->w_next)
7851 if (win->w_buffer == buf)
7852 break;
7853#else
7854 win = NULL;
7855#endif
7856
7857 /*
7858 * Prefer to use an existing window for the buffer, it has the least side
7859 * effects (esp. if "buf" is curbuf).
7860 * Otherwise, use curwin for "buf". It might make some items in the
7861 * window invalid. At least save the cursor and topline.
7862 */
7863 if (win != NULL)
7864 {
7865 /* there is a window for "buf", make it the curwin */
7866 aco->save_curwin = curwin;
7867 curwin = win;
7868 aco->save_buf = win->w_buffer;
7869 aco->new_curwin = win;
7870 }
7871 else
7872 {
7873 /* there is no window for "buf", use curwin */
7874 aco->save_curwin = NULL;
7875 aco->save_buf = curbuf;
7876 --curbuf->b_nwindows;
7877 curwin->w_buffer = buf;
7878 ++buf->b_nwindows;
7879
7880 /* save cursor and topline, set them to safe values */
7881 aco->save_cursor = curwin->w_cursor;
7882 curwin->w_cursor.lnum = 1;
7883 curwin->w_cursor.col = 0;
7884 aco->save_topline = curwin->w_topline;
7885 curwin->w_topline = 1;
7886#ifdef FEAT_DIFF
7887 aco->save_topfill = curwin->w_topfill;
7888 curwin->w_topfill = 0;
7889#endif
7890 }
7891
7892 curbuf = buf;
7893}
7894
7895/*
7896 * Cleanup after executing autocommands for a (hidden) buffer.
7897 * Restore the window as it was (if possible).
7898 */
7899 void
7900aucmd_restbuf(aco)
7901 aco_save_T *aco; /* structure holding saved values */
7902{
7903 if (aco->save_curwin != NULL)
7904 {
7905 /* restore curwin */
7906#ifdef FEAT_WINDOWS
7907 if (win_valid(aco->save_curwin))
7908#endif
7909 {
7910 /* restore the buffer which was previously edited by curwin, if
7911 * it's still the same window and it's valid */
7912 if (curwin == aco->new_curwin
7913 && buf_valid(aco->save_buf)
7914 && aco->save_buf->b_ml.ml_mfp != NULL)
7915 {
7916 --curbuf->b_nwindows;
7917 curbuf = aco->save_buf;
7918 curwin->w_buffer = curbuf;
7919 ++curbuf->b_nwindows;
7920 }
7921
7922 curwin = aco->save_curwin;
7923 curbuf = curwin->w_buffer;
7924 }
7925 }
7926 else
7927 {
7928 /* restore buffer for curwin if it still exists and is loaded */
7929 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
7930 {
7931 --curbuf->b_nwindows;
7932 curbuf = aco->save_buf;
7933 curwin->w_buffer = curbuf;
7934 ++curbuf->b_nwindows;
7935 curwin->w_cursor = aco->save_cursor;
7936 check_cursor();
7937 /* check topline < line_count, in case lines got deleted */
7938 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
7939 {
7940 curwin->w_topline = aco->save_topline;
7941#ifdef FEAT_DIFF
7942 curwin->w_topfill = aco->save_topfill;
7943#endif
7944 }
7945 else
7946 {
7947 curwin->w_topline = curbuf->b_ml.ml_line_count;
7948#ifdef FEAT_DIFF
7949 curwin->w_topfill = 0;
7950#endif
7951 }
7952 }
7953 }
7954}
7955
7956static int autocmd_nested = FALSE;
7957
7958/*
7959 * Execute autocommands for "event" and file name "fname".
7960 * Return TRUE if some commands were executed.
7961 */
7962 int
7963apply_autocmds(event, fname, fname_io, force, buf)
7964 EVENT_T event;
7965 char_u *fname; /* NULL or empty means use actual file name */
7966 char_u *fname_io; /* fname to use for <afile> on cmdline */
7967 int force; /* when TRUE, ignore autocmd_busy */
7968 buf_T *buf; /* buffer for <abuf> */
7969{
7970 return apply_autocmds_group(event, fname, fname_io, force,
7971 AUGROUP_ALL, buf, NULL);
7972}
7973
7974/*
7975 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
7976 * setting v:filearg.
7977 */
7978 static int
7979apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
7980 EVENT_T event;
7981 char_u *fname;
7982 char_u *fname_io;
7983 int force;
7984 buf_T *buf;
7985 exarg_T *eap;
7986{
7987 return apply_autocmds_group(event, fname, fname_io, force,
7988 AUGROUP_ALL, buf, eap);
7989}
7990
7991/*
7992 * Like apply_autocmds(), but handles the caller's retval. If the script
7993 * processing is being aborted or if retval is FAIL when inside a try
7994 * conditional, no autocommands are executed. If otherwise the autocommands
7995 * cause the script to be aborted, retval is set to FAIL.
7996 */
7997 int
7998apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
7999 EVENT_T event;
8000 char_u *fname; /* NULL or empty means use actual file name */
8001 char_u *fname_io; /* fname to use for <afile> on cmdline */
8002 int force; /* when TRUE, ignore autocmd_busy */
8003 buf_T *buf; /* buffer for <abuf> */
8004 int *retval; /* pointer to caller's retval */
8005{
8006 int did_cmd;
8007
Bram Moolenaar1e015462005-09-25 22:16:38 +00008008#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008009 if (should_abort(*retval))
8010 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00008011#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008012
8013 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
8014 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008015 if (did_cmd
8016#ifdef FEAT_EVAL
8017 && aborting()
8018#endif
8019 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008020 *retval = FAIL;
8021 return did_cmd;
8022}
8023
8024#if defined(FEAT_AUTOCMD) || defined(PROTO)
8025 int
8026has_cursorhold()
8027{
8028 return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
8029}
8030#endif
8031
8032 static int
8033apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
8034 EVENT_T event;
8035 char_u *fname; /* NULL or empty means use actual file name */
8036 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
8037 use fname */
8038 int force; /* when TRUE, ignore autocmd_busy */
8039 int group; /* group ID, or AUGROUP_ALL */
8040 buf_T *buf; /* buffer for <abuf> */
8041 exarg_T *eap; /* command arguments */
8042{
8043 char_u *sfname = NULL; /* short file name */
8044 char_u *tail;
8045 int save_changed;
8046 buf_T *old_curbuf;
8047 int retval = FALSE;
8048 char_u *save_sourcing_name;
8049 linenr_T save_sourcing_lnum;
8050 char_u *save_autocmd_fname;
8051 int save_autocmd_bufnr;
8052 char_u *save_autocmd_match;
8053 int save_autocmd_busy;
8054 int save_autocmd_nested;
8055 static int nesting = 0;
8056 AutoPatCmd patcmd;
8057 AutoPat *ap;
8058#ifdef FEAT_EVAL
8059 scid_T save_current_SID;
8060 void *save_funccalp;
8061 char_u *save_cmdarg;
8062 long save_cmdbang;
8063#endif
8064 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00008065#ifdef FEAT_PROFILE
8066 proftime_T wait_time;
8067#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008068
8069 /*
8070 * Quickly return if there are no autocommands for this event or
8071 * autocommands are blocked.
8072 */
8073 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008074 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008075
8076 /*
8077 * When autocommands are busy, new autocommands are only executed when
8078 * explicitly enabled with the "nested" flag.
8079 */
8080 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008081 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008082
8083#ifdef FEAT_EVAL
8084 /*
8085 * Quickly return when immdediately aborting on error, or when an interrupt
8086 * occurred or an exception was thrown but not caught.
8087 */
8088 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008089 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008090#endif
8091
8092 /*
8093 * FileChangedShell never nests, because it can create an endless loop.
8094 */
8095 if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008096 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008097
8098 /*
8099 * Ignore events in 'eventignore'.
8100 */
8101 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008102 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008103
8104 /*
8105 * Allow nesting of autocommands, but restrict the depth, because it's
8106 * possible to create an endless loop.
8107 */
8108 if (nesting == 10)
8109 {
8110 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008111 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008112 }
8113
8114 /*
8115 * Check if these autocommands are disabled. Used when doing ":all" or
8116 * ":ball".
8117 */
8118 if ( (autocmd_no_enter
8119 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
8120 || (autocmd_no_leave
8121 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008122 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008123
8124 /*
8125 * Save the autocmd_* variables and info about the current buffer.
8126 */
8127 save_autocmd_fname = autocmd_fname;
8128 save_autocmd_bufnr = autocmd_bufnr;
8129 save_autocmd_match = autocmd_match;
8130 save_autocmd_busy = autocmd_busy;
8131 save_autocmd_nested = autocmd_nested;
8132 save_changed = curbuf->b_changed;
8133 old_curbuf = curbuf;
8134
8135 /*
8136 * Set the file name to be used for <afile>.
8137 */
8138 if (fname_io == NULL)
8139 {
8140 if (fname != NULL && *fname != NUL)
8141 autocmd_fname = fname;
8142 else if (buf != NULL)
8143 autocmd_fname = buf->b_fname;
8144 else
8145 autocmd_fname = NULL;
8146 }
8147 else
8148 autocmd_fname = fname_io;
8149
8150 /*
8151 * Set the buffer number to be used for <abuf>.
8152 */
8153 if (buf == NULL)
8154 autocmd_bufnr = 0;
8155 else
8156 autocmd_bufnr = buf->b_fnum;
8157
8158 /*
8159 * When the file name is NULL or empty, use the file name of buffer "buf".
8160 * Always use the full path of the file name to match with, in case
8161 * "allow_dirs" is set.
8162 */
8163 if (fname == NULL || *fname == NUL)
8164 {
8165 if (buf == NULL)
8166 fname = NULL;
8167 else
8168 {
8169#ifdef FEAT_SYN_HL
8170 if (event == EVENT_SYNTAX)
8171 fname = buf->b_p_syn;
8172 else
8173#endif
8174 if (event == EVENT_FILETYPE)
8175 fname = buf->b_p_ft;
8176 else
8177 {
8178 if (buf->b_sfname != NULL)
8179 sfname = vim_strsave(buf->b_sfname);
8180 fname = buf->b_ffname;
8181 }
8182 }
8183 if (fname == NULL)
8184 fname = (char_u *)"";
8185 fname = vim_strsave(fname); /* make a copy, so we can change it */
8186 }
8187 else
8188 {
8189 sfname = vim_strsave(fname);
Bram Moolenaar7c626922005-02-07 22:01:03 +00008190 /* Don't try expanding FileType, Syntax, WindowID or QuickFixCmd* */
8191 if (event == EVENT_FILETYPE
8192 || event == EVENT_SYNTAX
8193 || event == EVENT_REMOTEREPLY
8194 || event == EVENT_QUICKFIXCMDPRE
8195 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008196 fname = vim_strsave(fname);
8197 else
8198 fname = FullName_save(fname, FALSE);
8199 }
8200 if (fname == NULL) /* out of memory */
8201 {
8202 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008203 retval = FALSE;
8204 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008205 }
8206
8207#ifdef BACKSLASH_IN_FILENAME
8208 /*
8209 * Replace all backslashes with forward slashes. This makes the
8210 * autocommand patterns portable between Unix and MS-DOS.
8211 */
8212 if (sfname != NULL)
8213 forward_slash(sfname);
8214 forward_slash(fname);
8215#endif
8216
8217#ifdef VMS
8218 /* remove version for correct match */
8219 if (sfname != NULL)
8220 vms_remove_version(sfname);
8221 vms_remove_version(fname);
8222#endif
8223
8224 /*
8225 * Set the name to be used for <amatch>.
8226 */
8227 autocmd_match = fname;
8228
8229
8230 /* Don't redraw while doing auto commands. */
8231 ++RedrawingDisabled;
8232 save_sourcing_name = sourcing_name;
8233 sourcing_name = NULL; /* don't free this one */
8234 save_sourcing_lnum = sourcing_lnum;
8235 sourcing_lnum = 0; /* no line number here */
8236
8237#ifdef FEAT_EVAL
8238 save_current_SID = current_SID;
8239
Bram Moolenaar05159a02005-02-26 23:04:13 +00008240# ifdef FEAT_PROFILE
8241 if (do_profiling)
8242 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
8243# endif
8244
Bram Moolenaar071d4272004-06-13 20:20:40 +00008245 /* Don't use local function variables, if called from a function */
8246 save_funccalp = save_funccal();
8247#endif
8248
8249 /*
8250 * When starting to execute autocommands, save the search patterns.
8251 */
8252 if (!autocmd_busy)
8253 {
8254 save_search_patterns();
8255 saveRedobuff();
8256 did_filetype = keep_filetype;
8257 }
8258
8259 /*
8260 * Note that we are applying autocmds. Some commands need to know.
8261 */
8262 autocmd_busy = TRUE;
8263 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
8264 ++nesting; /* see matching decrement below */
8265
8266 /* Remember that FileType was triggered. Used for did_filetype(). */
8267 if (event == EVENT_FILETYPE)
8268 did_filetype = TRUE;
8269
8270 tail = gettail(fname);
8271
8272 /* Find first autocommand that matches */
8273 patcmd.curpat = first_autopat[(int)event];
8274 patcmd.nextcmd = NULL;
8275 patcmd.group = group;
8276 patcmd.fname = fname;
8277 patcmd.sfname = sfname;
8278 patcmd.tail = tail;
8279 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008280 patcmd.arg_bufnr = autocmd_bufnr;
8281 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008282 auto_next_pat(&patcmd, FALSE);
8283
8284 /* found one, start executing the autocommands */
8285 if (patcmd.curpat != NULL)
8286 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008287 /* add to active_apc_list */
8288 patcmd.next = active_apc_list;
8289 active_apc_list = &patcmd;
8290
Bram Moolenaar071d4272004-06-13 20:20:40 +00008291#ifdef FEAT_EVAL
8292 /* set v:cmdarg (only when there is a matching pattern) */
8293 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
8294 if (eap != NULL)
8295 {
8296 save_cmdarg = set_cmdarg(eap, NULL);
8297 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
8298 }
8299 else
8300 save_cmdarg = NULL; /* avoid gcc warning */
8301#endif
8302 retval = TRUE;
8303 /* mark the last pattern, to avoid an endless loop when more patterns
8304 * are added when executing autocommands */
8305 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8306 ap->last = FALSE;
8307 ap->last = TRUE;
8308 check_lnums(TRUE); /* make sure cursor and topline are valid */
8309 do_cmdline(NULL, getnextac, (void *)&patcmd,
8310 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8311#ifdef FEAT_EVAL
8312 if (eap != NULL)
8313 {
8314 (void)set_cmdarg(NULL, save_cmdarg);
8315 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8316 }
8317#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008318 /* delete from active_apc_list */
8319 if (active_apc_list == &patcmd) /* just in case */
8320 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008321 }
8322
8323 --RedrawingDisabled;
8324 autocmd_busy = save_autocmd_busy;
8325 filechangeshell_busy = FALSE;
8326 autocmd_nested = save_autocmd_nested;
8327 vim_free(sourcing_name);
8328 sourcing_name = save_sourcing_name;
8329 sourcing_lnum = save_sourcing_lnum;
8330 autocmd_fname = save_autocmd_fname;
8331 autocmd_bufnr = save_autocmd_bufnr;
8332 autocmd_match = save_autocmd_match;
8333#ifdef FEAT_EVAL
8334 current_SID = save_current_SID;
8335 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00008336# ifdef FEAT_PROFILE
8337 if (do_profiling)
8338 prof_child_exit(&wait_time);
8339# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008340#endif
8341 vim_free(fname);
8342 vim_free(sfname);
8343 --nesting; /* see matching increment above */
8344
8345 /*
8346 * When stopping to execute autocommands, restore the search patterns and
8347 * the redo buffer.
8348 */
8349 if (!autocmd_busy)
8350 {
8351 restore_search_patterns();
8352 restoreRedobuff();
8353 did_filetype = FALSE;
8354 }
8355
8356 /*
8357 * Some events don't set or reset the Changed flag.
8358 * Check if still in the same buffer!
8359 */
8360 if (curbuf == old_curbuf
8361 && (event == EVENT_BUFREADPOST
8362 || event == EVENT_BUFWRITEPOST
8363 || event == EVENT_FILEAPPENDPOST
8364 || event == EVENT_VIMLEAVE
8365 || event == EVENT_VIMLEAVEPRE))
8366 {
8367#ifdef FEAT_TITLE
8368 if (curbuf->b_changed != save_changed)
8369 need_maketitle = TRUE;
8370#endif
8371 curbuf->b_changed = save_changed;
8372 }
8373
8374 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008375
8376BYPASS_AU:
8377 /* When wiping out a buffer make sure all its buffer-local autocommands
8378 * are deleted. */
8379 if (event == EVENT_BUFWIPEOUT && buf != NULL)
8380 aubuflocal_remove(buf);
8381
Bram Moolenaar071d4272004-06-13 20:20:40 +00008382 return retval;
8383}
8384
8385/*
8386 * Find next autocommand pattern that matches.
8387 */
8388 static void
8389auto_next_pat(apc, stop_at_last)
8390 AutoPatCmd *apc;
8391 int stop_at_last; /* stop when 'last' flag is set */
8392{
8393 AutoPat *ap;
8394 AutoCmd *cp;
8395 char_u *name;
8396 char *s;
8397
8398 vim_free(sourcing_name);
8399 sourcing_name = NULL;
8400
8401 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8402 {
8403 apc->curpat = NULL;
8404
8405 /* only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008406 * the group matches. For buffer-local autocommands only check the
8407 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008408 if (ap->pat != NULL && ap->cmds != NULL
8409 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8410 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008411 /* execution-condition */
8412 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008413 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
8414 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008415 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008416 {
8417 name = event_nr2name(apc->event);
8418 s = _("%s Auto commands for \"%s\"");
8419 sourcing_name = alloc((unsigned)(STRLEN(s)
8420 + STRLEN(name) + ap->patlen + 1));
8421 if (sourcing_name != NULL)
8422 {
8423 sprintf((char *)sourcing_name, s,
8424 (char *)name, (char *)ap->pat);
8425 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008426 {
8427 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008428 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008429 verbose_leave();
8430 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008431 }
8432
8433 apc->curpat = ap;
8434 apc->nextcmd = ap->cmds;
8435 /* mark last command */
8436 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8437 cp->last = FALSE;
8438 cp->last = TRUE;
8439 }
8440 line_breakcheck();
8441 if (apc->curpat != NULL) /* found a match */
8442 break;
8443 }
8444 if (stop_at_last && ap->last)
8445 break;
8446 }
8447}
8448
8449/*
8450 * Get next autocommand command.
8451 * Called by do_cmdline() to get the next line for ":if".
8452 * Returns allocated string, or NULL for end of autocommands.
8453 */
8454/* ARGSUSED */
8455 static char_u *
8456getnextac(c, cookie, indent)
8457 int c; /* not used */
8458 void *cookie;
8459 int indent; /* not used */
8460{
8461 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8462 char_u *retval;
8463 AutoCmd *ac;
8464
8465 /* Can be called again after returning the last line. */
8466 if (acp->curpat == NULL)
8467 return NULL;
8468
8469 /* repeat until we find an autocommand to execute */
8470 for (;;)
8471 {
8472 /* skip removed commands */
8473 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8474 if (acp->nextcmd->last)
8475 acp->nextcmd = NULL;
8476 else
8477 acp->nextcmd = acp->nextcmd->next;
8478
8479 if (acp->nextcmd != NULL)
8480 break;
8481
8482 /* at end of commands, find next pattern that matches */
8483 if (acp->curpat->last)
8484 acp->curpat = NULL;
8485 else
8486 acp->curpat = acp->curpat->next;
8487 if (acp->curpat != NULL)
8488 auto_next_pat(acp, TRUE);
8489 if (acp->curpat == NULL)
8490 return NULL;
8491 }
8492
8493 ac = acp->nextcmd;
8494
8495 if (p_verbose >= 9)
8496 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008497 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008498 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008499 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008500 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008501 }
8502 retval = vim_strsave(ac->cmd);
8503 autocmd_nested = ac->nested;
8504#ifdef FEAT_EVAL
8505 current_SID = ac->scriptID;
8506#endif
8507 if (ac->last)
8508 acp->nextcmd = NULL;
8509 else
8510 acp->nextcmd = ac->next;
8511 return retval;
8512}
8513
8514/*
8515 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008516 * To account for buffer-local autocommands, function needs to know
8517 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008518 */
8519 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008520has_autocmd(event, sfname, buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008521 EVENT_T event;
8522 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008523 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008524{
8525 AutoPat *ap;
8526 char_u *fname;
8527 char_u *tail = gettail(sfname);
8528 int retval = FALSE;
8529
8530 fname = FullName_save(sfname, FALSE);
8531 if (fname == NULL)
8532 return FALSE;
8533
8534#ifdef BACKSLASH_IN_FILENAME
8535 /*
8536 * Replace all backslashes with forward slashes. This makes the
8537 * autocommand patterns portable between Unix and MS-DOS.
8538 */
8539 sfname = vim_strsave(sfname);
8540 if (sfname != NULL)
8541 forward_slash(sfname);
8542 forward_slash(fname);
8543#endif
8544
8545 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8546 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008547 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008548 ? match_file_pat(NULL, ap->reg_prog,
8549 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008550 : buf != NULL && ap->buflocal_nr == buf->b_fnum
8551 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008552 {
8553 retval = TRUE;
8554 break;
8555 }
8556
8557 vim_free(fname);
8558#ifdef BACKSLASH_IN_FILENAME
8559 vim_free(sfname);
8560#endif
8561
8562 return retval;
8563}
8564
8565#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8566/*
8567 * Function given to ExpandGeneric() to obtain the list of autocommand group
8568 * names.
8569 */
8570/*ARGSUSED*/
8571 char_u *
8572get_augroup_name(xp, idx)
8573 expand_T *xp;
8574 int idx;
8575{
8576 if (idx == augroups.ga_len) /* add "END" add the end */
8577 return (char_u *)"END";
8578 if (idx >= augroups.ga_len) /* end of list */
8579 return NULL;
8580 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8581 return (char_u *)"";
8582 return AUGROUP_NAME(idx); /* return a name */
8583}
8584
8585static int include_groups = FALSE;
8586
8587 char_u *
8588set_context_in_autocmd(xp, arg, doautocmd)
8589 expand_T *xp;
8590 char_u *arg;
8591 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8592{
8593 char_u *p;
8594 int group;
8595
8596 /* check for a group name, skip it if present */
8597 include_groups = FALSE;
8598 p = arg;
8599 group = au_get_grouparg(&arg);
8600 if (group == AUGROUP_ERROR)
8601 return NULL;
8602 /* If there only is a group name that's what we expand. */
8603 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8604 {
8605 arg = p;
8606 group = AUGROUP_ALL;
8607 }
8608
8609 /* skip over event name */
8610 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8611 if (*p == ',')
8612 arg = p + 1;
8613 if (*p == NUL)
8614 {
8615 if (group == AUGROUP_ALL)
8616 include_groups = TRUE;
8617 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8618 xp->xp_pattern = arg;
8619 return NULL;
8620 }
8621
8622 /* skip over pattern */
8623 arg = skipwhite(p);
8624 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8625 arg++;
8626 if (*arg)
8627 return arg; /* expand (next) command */
8628
8629 if (doautocmd)
8630 xp->xp_context = EXPAND_FILES; /* expand file names */
8631 else
8632 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8633 return NULL;
8634}
8635
8636/*
8637 * Function given to ExpandGeneric() to obtain the list of event names.
8638 */
8639/*ARGSUSED*/
8640 char_u *
8641get_event_name(xp, idx)
8642 expand_T *xp;
8643 int idx;
8644{
8645 if (idx < augroups.ga_len) /* First list group names, if wanted */
8646 {
8647 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8648 return (char_u *)""; /* skip deleted entries */
8649 return AUGROUP_NAME(idx); /* return a name */
8650 }
8651 return (char_u *)event_names[idx - augroups.ga_len].name;
8652}
8653
8654#endif /* FEAT_CMDL_COMPL */
8655
8656/*
8657 * Return TRUE if an autocommand is defined for "event" and "pattern".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008658 * "pattern" can be NULL to accept any pattern. Buffer-local patterns
8659 * <buffer> or <buffer=N> are accepted.
8660 * Used for exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00008661 */
8662 int
8663au_exists(name, name_end, pattern)
8664 char_u *name;
8665 char_u *name_end;
8666 char_u *pattern;
8667{
8668 char_u *event_name;
8669 char_u *p;
8670 EVENT_T event;
8671 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008672 buf_T *buflocal_buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008673
8674 /* find the index (enum) for the event name */
8675 event_name = vim_strnsave(name, (int)(name_end - name));
8676 if (event_name == NULL)
8677 return FALSE;
8678 event = event_name2nr(event_name, &p);
8679 vim_free(event_name);
8680
8681 /* return FALSE if the event name is not recognized */
8682 if (event == NUM_EVENTS) /* unknown event name */
8683 return FALSE;
8684
8685 /* Find the first autocommand for this event.
8686 * If there isn't any, return FALSE;
8687 * If there is one and no pattern given, return TRUE; */
8688 ap = first_autopat[(int)event];
8689 if (ap == NULL)
8690 return FALSE;
8691 if (pattern == NULL)
8692 return TRUE;
8693
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008694 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
8695 /* for pattern "<buffer=N>, fnamecmp() will work fine */
8696 if (STRICMP(pattern, "<buffer>") == 0)
8697 buflocal_buf = curbuf;
8698
Bram Moolenaar071d4272004-06-13 20:20:40 +00008699 /* Check if there is an autocommand with the given pattern. */
8700 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008701 /* only use a pattern when it has not been removed and has commands. */
8702 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008703 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008704 && (buflocal_buf == NULL
8705 ? fnamecmp(ap->pat, pattern) == 0
8706 : ap->buflocal_nr == buflocal_buf->b_fnum))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008707 return TRUE;
8708
8709 return FALSE;
8710}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008711
Bram Moolenaar071d4272004-06-13 20:20:40 +00008712#endif /* FEAT_AUTOCMD */
8713
8714#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
8715/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00008716 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
8717 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
8718 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008719 * Used for autocommands and 'wildignore'.
8720 * Returns TRUE if there is a match, FALSE otherwise.
8721 */
8722 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00008723match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008724 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00008725 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008726 char_u *fname; /* full path of file name */
8727 char_u *sfname; /* short file name or NULL */
8728 char_u *tail; /* tail of path */
8729 int allow_dirs; /* allow matching with dir */
8730{
8731 regmatch_T regmatch;
8732 int result = FALSE;
8733#ifdef FEAT_OSFILETYPE
8734 int no_pattern = FALSE; /* TRUE if check is filetype only */
8735 char_u *type_start;
8736 char_u c;
8737 int match = FALSE;
8738#endif
8739
8740#ifdef CASE_INSENSITIVE_FILENAME
8741 regmatch.rm_ic = TRUE; /* Always ignore case */
8742#else
8743 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
8744#endif
8745#ifdef FEAT_OSFILETYPE
8746 if (*pattern == '<')
8747 {
8748 /* There is a filetype condition specified with this pattern.
8749 * Check the filetype matches first. If not, don't bother with the
8750 * pattern (set regprog to NULL).
8751 * Always use magic for the regexp.
8752 */
8753
8754 for (type_start = pattern + 1; (c = *pattern); pattern++)
8755 {
8756 if ((c == ';' || c == '>') && match == FALSE)
8757 {
8758 *pattern = NUL; /* Terminate the string */
8759 match = mch_check_filetype(fname, type_start);
8760 *pattern = c; /* Restore the terminator */
8761 type_start = pattern + 1;
8762 }
8763 if (c == '>')
8764 break;
8765 }
8766
8767 /* (c should never be NUL, but check anyway) */
8768 if (match == FALSE || c == NUL)
8769 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
8770 else if (*pattern == NUL)
8771 {
8772 regmatch.regprog = NULL; /* Vim will try to free regprog later */
8773 no_pattern = TRUE; /* Always matches - don't check pat. */
8774 }
8775 else
8776 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
8777 }
8778 else
8779#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00008780 {
8781 if (prog != NULL)
8782 regmatch.regprog = prog;
8783 else
8784 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
8785 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008786
8787 /*
8788 * Try for a match with the pattern with:
8789 * 1. the full file name, when the pattern has a '/'.
8790 * 2. the short file name, when the pattern has a '/'.
8791 * 3. the tail of the file name, when the pattern has no '/'.
8792 */
8793 if (
8794#ifdef FEAT_OSFILETYPE
8795 /* If the check is for a filetype only and we don't care
8796 * about the path then skip all the regexp stuff.
8797 */
8798 no_pattern ||
8799#endif
8800 (regmatch.regprog != NULL
8801 && ((allow_dirs
8802 && (vim_regexec(&regmatch, fname, (colnr_T)0)
8803 || (sfname != NULL
8804 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
8805 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
8806 result = TRUE;
8807
Bram Moolenaar748bf032005-02-02 23:04:36 +00008808 if (prog == NULL)
8809 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810 return result;
8811}
8812#endif
8813
8814#if defined(FEAT_WILDIGN) || defined(PROTO)
8815/*
8816 * Return TRUE if a file matches with a pattern in "list".
8817 * "list" is a comma-separated list of patterns, like 'wildignore'.
8818 * "sfname" is the short file name or NULL, "ffname" the long file name.
8819 */
8820 int
8821match_file_list(list, sfname, ffname)
8822 char_u *list;
8823 char_u *sfname;
8824 char_u *ffname;
8825{
8826 char_u buf[100];
8827 char_u *tail;
8828 char_u *regpat;
8829 char allow_dirs;
8830 int match;
8831 char_u *p;
8832
8833 tail = gettail(sfname);
8834
8835 /* try all patterns in 'wildignore' */
8836 p = list;
8837 while (*p)
8838 {
8839 copy_option_part(&p, buf, 100, ",");
8840 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
8841 if (regpat == NULL)
8842 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008843 match = match_file_pat(regpat, NULL, ffname, sfname,
8844 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008845 vim_free(regpat);
8846 if (match)
8847 return TRUE;
8848 }
8849 return FALSE;
8850}
8851#endif
8852
8853/*
8854 * Convert the given pattern "pat" which has shell style wildcards in it, into
8855 * a regular expression, and return the result in allocated memory. If there
8856 * is a directory path separator to be matched, then TRUE is put in
8857 * allow_dirs, otherwise FALSE is put there -- webb.
8858 * Handle backslashes before special characters, like "\*" and "\ ".
8859 *
8860 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
8861 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
8862 *
8863 * Returns NULL when out of memory.
8864 */
8865/*ARGSUSED*/
8866 char_u *
8867file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
8868 char_u *pat;
8869 char_u *pat_end; /* first char after pattern or NULL */
8870 char *allow_dirs; /* Result passed back out in here */
8871 int no_bslash; /* Don't use a backward slash as pathsep */
8872{
8873 int size;
8874 char_u *endp;
8875 char_u *reg_pat;
8876 char_u *p;
8877 int i;
8878 int nested = 0;
8879 int add_dollar = TRUE;
8880#ifdef FEAT_OSFILETYPE
8881 int check_length = 0;
8882#endif
8883
8884 if (allow_dirs != NULL)
8885 *allow_dirs = FALSE;
8886 if (pat_end == NULL)
8887 pat_end = pat + STRLEN(pat);
8888
8889#ifdef FEAT_OSFILETYPE
8890 /* Find out how much of the string is the filetype check */
8891 if (*pat == '<')
8892 {
8893 /* Count chars until the next '>' */
8894 for (p = pat + 1; p < pat_end && *p != '>'; p++)
8895 ;
8896 if (p < pat_end)
8897 {
8898 /* Pattern is of the form <.*>.* */
8899 check_length = p - pat + 1;
8900 if (p + 1 >= pat_end)
8901 {
8902 /* The 'pattern' is a filetype check ONLY */
8903 reg_pat = (char_u *)alloc(check_length + 1);
8904 if (reg_pat != NULL)
8905 {
8906 mch_memmove(reg_pat, pat, (size_t)check_length);
8907 reg_pat[check_length] = NUL;
8908 }
8909 return reg_pat;
8910 }
8911 }
8912 /* else: there was no closing '>' - assume it was a normal pattern */
8913
8914 }
8915 pat += check_length;
8916 size = 2 + check_length;
8917#else
8918 size = 2; /* '^' at start, '$' at end */
8919#endif
8920
8921 for (p = pat; p < pat_end; p++)
8922 {
8923 switch (*p)
8924 {
8925 case '*':
8926 case '.':
8927 case ',':
8928 case '{':
8929 case '}':
8930 case '~':
8931 size += 2; /* extra backslash */
8932 break;
8933#ifdef BACKSLASH_IN_FILENAME
8934 case '\\':
8935 case '/':
8936 size += 4; /* could become "[\/]" */
8937 break;
8938#endif
8939 default:
8940 size++;
8941# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00008942 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943 {
8944 ++p;
8945 ++size;
8946 }
8947# endif
8948 break;
8949 }
8950 }
8951 reg_pat = alloc(size + 1);
8952 if (reg_pat == NULL)
8953 return NULL;
8954
8955#ifdef FEAT_OSFILETYPE
8956 /* Copy the type check in to the start. */
8957 if (check_length)
8958 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
8959 i = check_length;
8960#else
8961 i = 0;
8962#endif
8963
8964 if (pat[0] == '*')
8965 while (pat[0] == '*' && pat < pat_end - 1)
8966 pat++;
8967 else
8968 reg_pat[i++] = '^';
8969 endp = pat_end - 1;
8970 if (*endp == '*')
8971 {
8972 while (endp - pat > 0 && *endp == '*')
8973 endp--;
8974 add_dollar = FALSE;
8975 }
8976 for (p = pat; *p && nested >= 0 && p <= endp; p++)
8977 {
8978 switch (*p)
8979 {
8980 case '*':
8981 reg_pat[i++] = '.';
8982 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +00008983 while (p[1] == '*') /* "**" matches like "*" */
8984 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008985 break;
8986 case '.':
8987#ifdef RISCOS
8988 if (allow_dirs != NULL)
8989 *allow_dirs = TRUE;
8990 /* FALLTHROUGH */
8991#endif
8992 case '~':
8993 reg_pat[i++] = '\\';
8994 reg_pat[i++] = *p;
8995 break;
8996 case '?':
8997#ifdef RISCOS
8998 case '#':
8999#endif
9000 reg_pat[i++] = '.';
9001 break;
9002 case '\\':
9003 if (p[1] == NUL)
9004 break;
9005#ifdef BACKSLASH_IN_FILENAME
9006 if (!no_bslash)
9007 {
9008 /* translate:
9009 * "\x" to "\\x" e.g., "dir\file"
9010 * "\*" to "\\.*" e.g., "dir\*.c"
9011 * "\?" to "\\." e.g., "dir\??.c"
9012 * "\+" to "\+" e.g., "fileX\+.c"
9013 */
9014 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
9015 && p[1] != '+')
9016 {
9017 reg_pat[i++] = '[';
9018 reg_pat[i++] = '\\';
9019 reg_pat[i++] = '/';
9020 reg_pat[i++] = ']';
9021 if (allow_dirs != NULL)
9022 *allow_dirs = TRUE;
9023 break;
9024 }
9025 }
9026#endif
9027 if (*++p == '?'
9028#ifdef BACKSLASH_IN_FILENAME
9029 && no_bslash
9030#endif
9031 )
9032 reg_pat[i++] = '?';
9033 else
9034 if (*p == ',')
9035 reg_pat[i++] = ',';
9036 else
9037 {
9038 if (allow_dirs != NULL && vim_ispathsep(*p)
9039#ifdef BACKSLASH_IN_FILENAME
9040 && (!no_bslash || *p != '\\')
9041#endif
9042 )
9043 *allow_dirs = TRUE;
9044 reg_pat[i++] = '\\';
9045 reg_pat[i++] = *p;
9046 }
9047 break;
9048#ifdef BACKSLASH_IN_FILENAME
9049 case '/':
9050 reg_pat[i++] = '[';
9051 reg_pat[i++] = '\\';
9052 reg_pat[i++] = '/';
9053 reg_pat[i++] = ']';
9054 if (allow_dirs != NULL)
9055 *allow_dirs = TRUE;
9056 break;
9057#endif
9058 case '{':
9059 reg_pat[i++] = '\\';
9060 reg_pat[i++] = '(';
9061 nested++;
9062 break;
9063 case '}':
9064 reg_pat[i++] = '\\';
9065 reg_pat[i++] = ')';
9066 --nested;
9067 break;
9068 case ',':
9069 if (nested)
9070 {
9071 reg_pat[i++] = '\\';
9072 reg_pat[i++] = '|';
9073 }
9074 else
9075 reg_pat[i++] = ',';
9076 break;
9077 default:
9078# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009079 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009080 reg_pat[i++] = *p++;
9081 else
9082# endif
9083 if (allow_dirs != NULL && vim_ispathsep(*p))
9084 *allow_dirs = TRUE;
9085 reg_pat[i++] = *p;
9086 break;
9087 }
9088 }
9089 if (add_dollar)
9090 reg_pat[i++] = '$';
9091 reg_pat[i] = NUL;
9092 if (nested != 0)
9093 {
9094 if (nested < 0)
9095 EMSG(_("E219: Missing {."));
9096 else
9097 EMSG(_("E220: Missing }."));
9098 vim_free(reg_pat);
9099 reg_pat = NULL;
9100 }
9101 return reg_pat;
9102}