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