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