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