blob: 27d8ed7e709d30aba3c2ac7c69247b0b20c1c82e [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
Bram Moolenaarc1e37902006-04-18 21:55:01 +00001116 for ( ; size >= 10; size = (long)((long_u)size >> 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 {
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 */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001146 real_size = (int)size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147# 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. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001203 n = (int)(size - tlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001204 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. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001491 bytelen = (int)utf_ptr2len_len(src, size);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001492 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,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001562 (LPSTR)dst, (int)(src - dst),
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001563 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. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001602 size = (long)(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 Moolenaara93fa7e2006-04-17 22:14:47 +00001843 int todo = (int)((ptr + size) - p);
Bram Moolenaarb0bf8582005-12-13 20:02:15 +00001844 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 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004541 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004542
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 Moolenaara93fa7e2006-04-17 22:14:47 +00004961 n = (int)utf_ptr2len_len(from, (int)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);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004980 ip->bw_restlen = (int)fromlen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981 }
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,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004988 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004989 NULL, 0);
4990 if (needed == 0)
4991 {
4992 /* When conversion fails there may be a trailing byte. */
4993 needed = MultiByteToWideChar(enc_codepage,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004994 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004995 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,
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005007 (LPCSTR)from, (int)(fromlen - ip->bw_restlen),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005008 (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 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005036 len = (int)(to - buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037 }
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),
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005047 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0, &bad);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005048 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);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006485 if (savebuf != NULL && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006486 {
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 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006494 if (savebuf == NULL || saved == FAIL || buf != curbuf
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006495 || 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);
Bram Moolenaar8424a622006-04-19 21:23:36 +00006517 if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006518 {
6519 /* Put the text back from the save buffer. First
6520 * delete any lines that readfile() added. */
6521 while (!bufempty())
Bram Moolenaar8424a622006-04-19 21:23:36 +00006522 if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006523 break;
6524 (void)move_lines(savebuf, buf);
6525 }
6526 }
Bram Moolenaar8424a622006-04-19 21:23:36 +00006527 else if (buf == curbuf)
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006528 {
6529 /* Mark the buffer as unmodified and free undo info. */
6530 unchanged(buf, TRUE);
6531 u_blockfree(buf);
6532 u_clearall(buf);
6533 }
6534 }
6535 vim_free(ea.cmd);
6536
Bram Moolenaar8424a622006-04-19 21:23:36 +00006537 if (savebuf != NULL && buf_valid(savebuf))
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006538 wipe_buffer(savebuf, FALSE);
6539
6540#ifdef FEAT_DIFF
6541 /* Invalidate diff info if necessary. */
Bram Moolenaar8424a622006-04-19 21:23:36 +00006542 diff_invalidate(curbuf);
Bram Moolenaar631d6f62005-06-07 21:02:10 +00006543#endif
6544
6545 /* Restore the topline and cursor position and check it (lines may
6546 * have been removed). */
6547 if (old_topline > curbuf->b_ml.ml_line_count)
6548 curwin->w_topline = curbuf->b_ml.ml_line_count;
6549 else
6550 curwin->w_topline = old_topline;
6551 curwin->w_cursor = old_cursor;
6552 check_cursor();
6553 update_topline();
6554#ifdef FEAT_AUTOCMD
6555 keep_filetype = FALSE;
6556#endif
6557#ifdef FEAT_FOLDING
6558 {
6559 win_T *wp;
6560
6561 /* Update folds unless they are defined manually. */
6562 FOR_ALL_WINDOWS(wp)
6563 if (wp->w_buffer == curwin->w_buffer
6564 && !foldmethodIsManual(wp))
6565 foldUpdateAll(wp);
6566 }
6567#endif
6568 /* If the mode didn't change and 'readonly' was set, keep the old
6569 * value; the user probably used the ":view" command. But don't
6570 * reset it, might have had a read error. */
6571 if (orig_mode == curbuf->b_orig_mode)
6572 curbuf->b_p_ro |= old_ro;
6573 }
6574
6575#ifdef FEAT_AUTOCMD
6576 /* restore curwin/curbuf and a few other things */
6577 aucmd_restbuf(&aco);
6578 /* Careful: autocommands may have made "buf" invalid! */
6579#else
6580 curwin->w_buffer = save_curbuf;
6581 curbuf = save_curbuf;
6582#endif
6583}
6584
Bram Moolenaar071d4272004-06-13 20:20:40 +00006585/*ARGSUSED*/
6586 void
6587buf_store_time(buf, st, fname)
6588 buf_T *buf;
6589 struct stat *st;
6590 char_u *fname;
6591{
6592 buf->b_mtime = (long)st->st_mtime;
6593 buf->b_orig_size = (size_t)st->st_size;
6594#ifdef HAVE_ST_MODE
6595 buf->b_orig_mode = (int)st->st_mode;
6596#else
6597 buf->b_orig_mode = mch_getperm(fname);
6598#endif
6599}
6600
6601/*
6602 * Adjust the line with missing eol, used for the next write.
6603 * Used for do_filter(), when the input lines for the filter are deleted.
6604 */
6605 void
6606write_lnum_adjust(offset)
6607 linenr_T offset;
6608{
Bram Moolenaardf177f62005-02-22 08:39:57 +00006609 if (write_no_eol_lnum != 0) /* only if there is a missing eol */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006610 write_no_eol_lnum += offset;
6611}
6612
6613#if defined(TEMPDIRNAMES) || defined(PROTO)
6614static long temp_count = 0; /* Temp filename counter. */
6615
6616/*
6617 * Delete the temp directory and all files it contains.
6618 */
6619 void
6620vim_deltempdir()
6621{
6622 char_u **files;
6623 int file_count;
6624 int i;
6625
6626 if (vim_tempdir != NULL)
6627 {
6628 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6629 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6630 EW_DIR|EW_FILE|EW_SILENT) == OK)
6631 {
6632 for (i = 0; i < file_count; ++i)
6633 mch_remove(files[i]);
6634 FreeWild(file_count, files);
6635 }
6636 gettail(NameBuff)[-1] = NUL;
6637 (void)mch_rmdir(NameBuff);
6638
6639 vim_free(vim_tempdir);
6640 vim_tempdir = NULL;
6641 }
6642}
6643#endif
6644
6645/*
6646 * vim_tempname(): Return a unique name that can be used for a temp file.
6647 *
6648 * The temp file is NOT created.
6649 *
6650 * The returned pointer is to allocated memory.
6651 * The returned pointer is NULL if no valid name was found.
6652 */
6653/*ARGSUSED*/
6654 char_u *
6655vim_tempname(extra_char)
6656 int extra_char; /* character to use in the name instead of '?' */
6657{
6658#ifdef USE_TMPNAM
6659 char_u itmp[L_tmpnam]; /* use tmpnam() */
6660#else
6661 char_u itmp[TEMPNAMELEN];
6662#endif
6663
6664#ifdef TEMPDIRNAMES
6665 static char *(tempdirs[]) = {TEMPDIRNAMES};
6666 int i;
6667 long nr;
6668 long off;
6669# ifndef EEXIST
6670 struct stat st;
6671# endif
6672
6673 /*
6674 * This will create a directory for private use by this instance of Vim.
6675 * This is done once, and the same directory is used for all temp files.
6676 * This method avoids security problems because of symlink attacks et al.
6677 * It's also a bit faster, because we only need to check for an existing
6678 * file when creating the directory and not for each temp file.
6679 */
6680 if (vim_tempdir == NULL)
6681 {
6682 /*
6683 * Try the entries in TEMPDIRNAMES to create the temp directory.
6684 */
6685 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6686 {
6687 /* expand $TMP, leave room for "/v1100000/999999999" */
6688 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6689 if (mch_isdir(itmp)) /* directory exists */
6690 {
6691# ifdef __EMX__
6692 /* If $TMP contains a forward slash (perhaps using bash or
6693 * tcsh), don't add a backslash, use a forward slash!
6694 * Adding 2 backslashes didn't work. */
6695 if (vim_strchr(itmp, '/') != NULL)
6696 STRCAT(itmp, "/");
6697 else
6698# endif
6699 add_pathsep(itmp);
6700
6701 /* Get an arbitrary number of up to 6 digits. When it's
6702 * unlikely that it already exists it will be faster,
6703 * otherwise it doesn't matter. The use of mkdir() avoids any
6704 * security problems because of the predictable number. */
6705 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6706
6707 /* Try up to 10000 different values until we find a name that
6708 * doesn't exist. */
6709 for (off = 0; off < 10000L; ++off)
6710 {
6711 int r;
6712#if defined(UNIX) || defined(VMS)
6713 mode_t umask_save;
6714#endif
6715
6716 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6717# ifndef EEXIST
6718 /* If mkdir() does not set errno to EEXIST, check for
6719 * existing file here. There is a race condition then,
6720 * although it's fail-safe. */
6721 if (mch_stat((char *)itmp, &st) >= 0)
6722 continue;
6723# endif
6724#if defined(UNIX) || defined(VMS)
6725 /* Make sure the umask doesn't remove the executable bit.
6726 * "repl" has been reported to use "177". */
6727 umask_save = umask(077);
6728#endif
6729 r = vim_mkdir(itmp, 0700);
6730#if defined(UNIX) || defined(VMS)
6731 (void)umask(umask_save);
6732#endif
6733 if (r == 0)
6734 {
6735 char_u *buf;
6736
6737 /* Directory was created, use this name.
6738 * Expand to full path; When using the current
6739 * directory a ":cd" would confuse us. */
6740 buf = alloc((unsigned)MAXPATHL + 1);
6741 if (buf != NULL)
6742 {
6743 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6744 == FAIL)
6745 STRCPY(buf, itmp);
6746# ifdef __EMX__
6747 if (vim_strchr(buf, '/') != NULL)
6748 STRCAT(buf, "/");
6749 else
6750# endif
6751 add_pathsep(buf);
6752 vim_tempdir = vim_strsave(buf);
6753 vim_free(buf);
6754 }
6755 break;
6756 }
6757# ifdef EEXIST
6758 /* If the mkdir() didn't fail because the file/dir exists,
6759 * we probably can't create any dir here, try another
6760 * place. */
6761 if (errno != EEXIST)
6762# endif
6763 break;
6764 }
6765 if (vim_tempdir != NULL)
6766 break;
6767 }
6768 }
6769 }
6770
6771 if (vim_tempdir != NULL)
6772 {
6773 /* There is no need to check if the file exists, because we own the
6774 * directory and nobody else creates a file in it. */
6775 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6776 return vim_strsave(itmp);
6777 }
6778
6779 return NULL;
6780
6781#else /* TEMPDIRNAMES */
6782
6783# ifdef WIN3264
6784 char szTempFile[_MAX_PATH + 1];
6785 char buf4[4];
6786 char_u *retval;
6787 char_u *p;
6788
6789 STRCPY(itmp, "");
6790 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6791 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6792 strcpy(buf4, "VIM");
6793 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6794 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6795 return NULL;
6796 /* GetTempFileName() will create the file, we don't want that */
6797 (void)DeleteFile(itmp);
6798
6799 /* Backslashes in a temp file name cause problems when filtering with
6800 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6801 * didn't set 'shellslash'. */
6802 retval = vim_strsave(itmp);
6803 if (*p_shcf == '-' || p_ssl)
6804 for (p = retval; *p; ++p)
6805 if (*p == '\\')
6806 *p = '/';
6807 return retval;
6808
6809# else /* WIN3264 */
6810
6811# ifdef USE_TMPNAM
6812 /* tmpnam() will make its own name */
6813 if (*tmpnam((char *)itmp) == NUL)
6814 return NULL;
6815# else
6816 char_u *p;
6817
6818# ifdef VMS_TEMPNAM
6819 /* mktemp() is not working on VMS. It seems to be
6820 * a do-nothing function. Therefore we use tempnam().
6821 */
6822 sprintf((char *)itmp, "VIM%c", extra_char);
6823 p = (char_u *)tempnam("tmp:", (char *)itmp);
6824 if (p != NULL)
6825 {
6826 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6827 * and VIM will then be unable to find the file later */
6828 STRCPY(itmp, p);
6829 STRCAT(itmp, ".txt");
6830 free(p);
6831 }
6832 else
6833 return NULL;
6834# else
6835 STRCPY(itmp, TEMPNAME);
6836 if ((p = vim_strchr(itmp, '?')) != NULL)
6837 *p = extra_char;
6838 if (mktemp((char *)itmp) == NULL)
6839 return NULL;
6840# endif
6841# endif
6842
6843 return vim_strsave(itmp);
6844# endif /* WIN3264 */
6845#endif /* TEMPDIRNAMES */
6846}
6847
6848#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6849/*
6850 * Convert all backslashes in fname to forward slashes in-place.
6851 */
6852 void
6853forward_slash(fname)
6854 char_u *fname;
6855{
6856 char_u *p;
6857
6858 for (p = fname; *p != NUL; ++p)
6859# ifdef FEAT_MBYTE
6860 /* The Big5 encoding can have '\' in the trail byte. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00006861 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006862 ++p;
6863 else
6864# endif
6865 if (*p == '\\')
6866 *p = '/';
6867}
6868#endif
6869
6870
6871/*
6872 * Code for automatic commands.
6873 *
6874 * Only included when "FEAT_AUTOCMD" has been defined.
6875 */
6876
6877#if defined(FEAT_AUTOCMD) || defined(PROTO)
6878
6879/*
6880 * The autocommands are stored in a list for each event.
6881 * Autocommands for the same pattern, that are consecutive, are joined
6882 * together, to avoid having to match the pattern too often.
6883 * The result is an array of Autopat lists, which point to AutoCmd lists:
6884 *
6885 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6886 * Autopat.cmds Autopat.cmds
6887 * | |
6888 * V V
6889 * AutoCmd.next AutoCmd.next
6890 * | |
6891 * V V
6892 * AutoCmd.next NULL
6893 * |
6894 * V
6895 * NULL
6896 *
6897 * first_autopat[1] --> Autopat.next --> NULL
6898 * Autopat.cmds
6899 * |
6900 * V
6901 * AutoCmd.next
6902 * |
6903 * V
6904 * NULL
6905 * etc.
6906 *
6907 * The order of AutoCmds is important, this is the order in which they were
6908 * defined and will have to be executed.
6909 */
6910typedef struct AutoCmd
6911{
6912 char_u *cmd; /* The command to be executed (NULL
6913 when command has been removed) */
6914 char nested; /* If autocommands nest here */
6915 char last; /* last command in list */
6916#ifdef FEAT_EVAL
6917 scid_T scriptID; /* script ID where defined */
6918#endif
6919 struct AutoCmd *next; /* Next AutoCmd in list */
6920} AutoCmd;
6921
6922typedef struct AutoPat
6923{
6924 int group; /* group ID */
6925 char_u *pat; /* pattern as typed (NULL when pattern
6926 has been removed) */
6927 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00006928 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006929 char allow_dirs; /* Pattern may match whole path */
6930 char last; /* last pattern for apply_autocmds() */
6931 AutoCmd *cmds; /* list of commands to do */
6932 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006933 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934} AutoPat;
6935
6936static struct event_name
6937{
6938 char *name; /* event name */
Bram Moolenaar754b5602006-02-09 23:53:20 +00006939 event_T event; /* event number */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006940} event_names[] =
6941{
6942 {"BufAdd", EVENT_BUFADD},
6943 {"BufCreate", EVENT_BUFADD},
6944 {"BufDelete", EVENT_BUFDELETE},
6945 {"BufEnter", EVENT_BUFENTER},
6946 {"BufFilePost", EVENT_BUFFILEPOST},
6947 {"BufFilePre", EVENT_BUFFILEPRE},
6948 {"BufHidden", EVENT_BUFHIDDEN},
6949 {"BufLeave", EVENT_BUFLEAVE},
6950 {"BufNew", EVENT_BUFNEW},
6951 {"BufNewFile", EVENT_BUFNEWFILE},
6952 {"BufRead", EVENT_BUFREADPOST},
6953 {"BufReadCmd", EVENT_BUFREADCMD},
6954 {"BufReadPost", EVENT_BUFREADPOST},
6955 {"BufReadPre", EVENT_BUFREADPRE},
6956 {"BufUnload", EVENT_BUFUNLOAD},
6957 {"BufWinEnter", EVENT_BUFWINENTER},
6958 {"BufWinLeave", EVENT_BUFWINLEAVE},
6959 {"BufWipeout", EVENT_BUFWIPEOUT},
6960 {"BufWrite", EVENT_BUFWRITEPRE},
6961 {"BufWritePost", EVENT_BUFWRITEPOST},
6962 {"BufWritePre", EVENT_BUFWRITEPRE},
6963 {"BufWriteCmd", EVENT_BUFWRITECMD},
6964 {"CmdwinEnter", EVENT_CMDWINENTER},
6965 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006966 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar754b5602006-02-09 23:53:20 +00006967 {"CursorHold", EVENT_CURSORHOLD},
6968 {"CursorHoldI", EVENT_CURSORHOLDI},
6969 {"CursorMoved", EVENT_CURSORMOVED},
6970 {"CursorMovedI", EVENT_CURSORMOVEDI},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006971 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6972 {"FileEncoding", EVENT_ENCODINGCHANGED},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006973 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6974 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6975 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6976 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
Bram Moolenaar56718732006-03-15 22:53:57 +00006977 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006978 {"FileChangedRO", EVENT_FILECHANGEDRO},
6979 {"FileReadPost", EVENT_FILEREADPOST},
6980 {"FileReadPre", EVENT_FILEREADPRE},
6981 {"FileReadCmd", EVENT_FILEREADCMD},
6982 {"FileType", EVENT_FILETYPE},
6983 {"FileWritePost", EVENT_FILEWRITEPOST},
6984 {"FileWritePre", EVENT_FILEWRITEPRE},
6985 {"FileWriteCmd", EVENT_FILEWRITECMD},
6986 {"FilterReadPost", EVENT_FILTERREADPOST},
6987 {"FilterReadPre", EVENT_FILTERREADPRE},
6988 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6989 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6990 {"FocusGained", EVENT_FOCUSGAINED},
6991 {"FocusLost", EVENT_FOCUSLOST},
6992 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6993 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006994 {"InsertChange", EVENT_INSERTCHANGE},
6995 {"InsertEnter", EVENT_INSERTENTER},
6996 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaara3ffd9c2005-07-21 21:03:15 +00006997 {"MenuPopup", EVENT_MENUPOPUP},
Bram Moolenaar7c626922005-02-07 22:01:03 +00006998 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
6999 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007000 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar9372a112005-12-06 19:59:18 +00007001 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
Bram Moolenaar5c4bab02006-03-10 21:37:46 +00007002 {"ShellCmdPost", EVENT_SHELLCMDPOST},
7003 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
Bram Moolenaara2031822006-03-07 22:29:51 +00007004 {"SourcePre", EVENT_SOURCEPRE},
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00007005 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007006 {"StdinReadPost", EVENT_STDINREADPOST},
7007 {"StdinReadPre", EVENT_STDINREADPRE},
Bram Moolenaarb815dac2005-12-07 20:59:24 +00007008 {"SwapExists", EVENT_SWAPEXISTS},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007009 {"Syntax", EVENT_SYNTAX},
Bram Moolenaar70836c82006-02-20 21:28:49 +00007010 {"TabEnter", EVENT_TABENTER},
7011 {"TabLeave", EVENT_TABLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007012 {"TermChanged", EVENT_TERMCHANGED},
7013 {"TermResponse", EVENT_TERMRESPONSE},
7014 {"User", EVENT_USER},
7015 {"VimEnter", EVENT_VIMENTER},
7016 {"VimLeave", EVENT_VIMLEAVE},
7017 {"VimLeavePre", EVENT_VIMLEAVEPRE},
7018 {"WinEnter", EVENT_WINENTER},
7019 {"WinLeave", EVENT_WINLEAVE},
Bram Moolenaar56718732006-03-15 22:53:57 +00007020 {"VimResized", EVENT_VIMRESIZED},
Bram Moolenaar754b5602006-02-09 23:53:20 +00007021 {NULL, (event_T)0}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007022};
7023
7024static AutoPat *first_autopat[NUM_EVENTS] =
7025{
7026 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
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,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007030 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
7031 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007032};
7033
7034/*
7035 * struct used to keep status while executing autocommands for an event.
7036 */
7037typedef struct AutoPatCmd
7038{
7039 AutoPat *curpat; /* next AutoPat to examine */
7040 AutoCmd *nextcmd; /* next AutoCmd to execute */
7041 int group; /* group being used */
7042 char_u *fname; /* fname to match with */
7043 char_u *sfname; /* sfname to match with */
7044 char_u *tail; /* tail of fname */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007045 event_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007046 int arg_bufnr; /* initially equal to <abuf>, set to zero when
7047 buf is deleted */
7048 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00007049} AutoPatCmd;
7050
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007051static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007052
Bram Moolenaar071d4272004-06-13 20:20:40 +00007053/*
7054 * augroups stores a list of autocmd group names.
7055 */
Bram Moolenaard6f676d2005-06-01 21:51:55 +00007056static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00007057#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
7058
7059/*
7060 * The ID of the current group. Group 0 is the default one.
7061 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007062static int current_augroup = AUGROUP_DEFAULT;
7063
7064static int au_need_clean = FALSE; /* need to delete marked patterns */
7065
Bram Moolenaar754b5602006-02-09 23:53:20 +00007066static void show_autocmd __ARGS((AutoPat *ap, event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007067static void au_remove_pat __ARGS((AutoPat *ap));
7068static void au_remove_cmds __ARGS((AutoPat *ap));
7069static void au_cleanup __ARGS((void));
7070static int au_new_group __ARGS((char_u *name));
7071static void au_del_group __ARGS((char_u *name));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007072static event_T event_name2nr __ARGS((char_u *start, char_u **end));
7073static char_u *event_nr2name __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007074static char_u *find_end_event __ARGS((char_u *arg, int have_group));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007075static int event_ignored __ARGS((event_T event));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007076static int au_get_grouparg __ARGS((char_u **argp));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007077static 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 +00007078static char_u *getnextac __ARGS((int c, void *cookie, int indent));
Bram Moolenaar754b5602006-02-09 23:53:20 +00007079static 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 +00007080static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
7081
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007082
Bram Moolenaar754b5602006-02-09 23:53:20 +00007083static event_T last_event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007084static int last_group;
7085
7086/*
7087 * Show the autocommands for one AutoPat.
7088 */
7089 static void
7090show_autocmd(ap, event)
7091 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007092 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007093{
7094 AutoCmd *ac;
7095
7096 /* Check for "got_int" (here and at various places below), which is set
7097 * when "q" has been hit for the "--more--" prompt */
7098 if (got_int)
7099 return;
7100 if (ap->pat == NULL) /* pattern has been removed */
7101 return;
7102
7103 msg_putchar('\n');
7104 if (got_int)
7105 return;
7106 if (event != last_event || ap->group != last_group)
7107 {
7108 if (ap->group != AUGROUP_DEFAULT)
7109 {
7110 if (AUGROUP_NAME(ap->group) == NULL)
7111 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
7112 else
7113 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
7114 msg_puts((char_u *)" ");
7115 }
7116 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
7117 last_event = event;
7118 last_group = ap->group;
7119 msg_putchar('\n');
7120 if (got_int)
7121 return;
7122 }
7123 msg_col = 4;
7124 msg_outtrans(ap->pat);
7125
7126 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7127 {
7128 if (ac->cmd != NULL) /* skip removed commands */
7129 {
7130 if (msg_col >= 14)
7131 msg_putchar('\n');
7132 msg_col = 14;
7133 if (got_int)
7134 return;
7135 msg_outtrans(ac->cmd);
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00007136#ifdef FEAT_EVAL
7137 if (p_verbose > 0)
7138 last_set_msg(ac->scriptID);
7139#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007140 if (got_int)
7141 return;
7142 if (ac->next != NULL)
7143 {
7144 msg_putchar('\n');
7145 if (got_int)
7146 return;
7147 }
7148 }
7149 }
7150}
7151
7152/*
7153 * Mark an autocommand pattern for deletion.
7154 */
7155 static void
7156au_remove_pat(ap)
7157 AutoPat *ap;
7158{
7159 vim_free(ap->pat);
7160 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007161 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007162 au_need_clean = TRUE;
7163}
7164
7165/*
7166 * Mark all commands for a pattern for deletion.
7167 */
7168 static void
7169au_remove_cmds(ap)
7170 AutoPat *ap;
7171{
7172 AutoCmd *ac;
7173
7174 for (ac = ap->cmds; ac != NULL; ac = ac->next)
7175 {
7176 vim_free(ac->cmd);
7177 ac->cmd = NULL;
7178 }
7179 au_need_clean = TRUE;
7180}
7181
7182/*
7183 * Cleanup autocommands and patterns that have been deleted.
7184 * This is only done when not executing autocommands.
7185 */
7186 static void
7187au_cleanup()
7188{
7189 AutoPat *ap, **prev_ap;
7190 AutoCmd *ac, **prev_ac;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007191 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007192
7193 if (autocmd_busy || !au_need_clean)
7194 return;
7195
7196 /* loop over all events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007197 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7198 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007199 {
7200 /* loop over all autocommand patterns */
7201 prev_ap = &(first_autopat[(int)event]);
7202 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
7203 {
7204 /* loop over all commands for this pattern */
7205 prev_ac = &(ap->cmds);
7206 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
7207 {
7208 /* remove the command if the pattern is to be deleted or when
7209 * the command has been marked for deletion */
7210 if (ap->pat == NULL || ac->cmd == NULL)
7211 {
7212 *prev_ac = ac->next;
7213 vim_free(ac->cmd);
7214 vim_free(ac);
7215 }
7216 else
7217 prev_ac = &(ac->next);
7218 }
7219
7220 /* remove the pattern if it has been marked for deletion */
7221 if (ap->pat == NULL)
7222 {
7223 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007224 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007225 vim_free(ap);
7226 }
7227 else
7228 prev_ap = &(ap->next);
7229 }
7230 }
7231
7232 au_need_clean = FALSE;
7233}
7234
7235/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007236 * Called when buffer is freed, to remove/invalidate related buffer-local
7237 * autocmds.
7238 */
7239 void
7240aubuflocal_remove(buf)
7241 buf_T *buf;
7242{
7243 AutoPat *ap;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007244 event_T event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007245 AutoPatCmd *apc;
7246
7247 /* invalidate currently executing autocommands */
7248 for (apc = active_apc_list; apc; apc = apc->next)
7249 if (buf->b_fnum == apc->arg_bufnr)
7250 apc->arg_bufnr = 0;
7251
7252 /* invalidate buflocals looping through events */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007253 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7254 event = (event_T)((int)event + 1))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007255 /* loop over all autocommand patterns */
7256 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7257 if (ap->buflocal_nr == buf->b_fnum)
7258 {
7259 au_remove_pat(ap);
7260 if (p_verbose >= 6)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007261 {
7262 verbose_enter();
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007263 smsg((char_u *)
7264 _("auto-removing autocommand: %s <buffer=%d>"),
7265 event_nr2name(event), buf->b_fnum);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007266 verbose_leave();
7267 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007268 }
7269 au_cleanup();
7270}
7271
7272/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007273 * Add an autocmd group name.
7274 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7275 */
7276 static int
7277au_new_group(name)
7278 char_u *name;
7279{
7280 int i;
7281
7282 i = au_find_group(name);
7283 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
7284 {
7285 /* First try using a free entry. */
7286 for (i = 0; i < augroups.ga_len; ++i)
7287 if (AUGROUP_NAME(i) == NULL)
7288 break;
7289 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
7290 return AUGROUP_ERROR;
7291
7292 AUGROUP_NAME(i) = vim_strsave(name);
7293 if (AUGROUP_NAME(i) == NULL)
7294 return AUGROUP_ERROR;
7295 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007296 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007297 }
7298
7299 return i;
7300}
7301
7302 static void
7303au_del_group(name)
7304 char_u *name;
7305{
7306 int i;
7307
7308 i = au_find_group(name);
7309 if (i == AUGROUP_ERROR) /* the group doesn't exist */
7310 EMSG2(_("E367: No such group: \"%s\""), name);
7311 else
7312 {
7313 vim_free(AUGROUP_NAME(i));
7314 AUGROUP_NAME(i) = NULL;
7315 }
7316}
7317
7318/*
7319 * Find the ID of an autocmd group name.
7320 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
7321 */
7322 static int
7323au_find_group(name)
7324 char_u *name;
7325{
7326 int i;
7327
7328 for (i = 0; i < augroups.ga_len; ++i)
7329 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
7330 return i;
7331 return AUGROUP_ERROR;
7332}
7333
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007334/*
7335 * Return TRUE if augroup "name" exists.
7336 */
7337 int
7338au_has_group(name)
7339 char_u *name;
7340{
7341 return au_find_group(name) != AUGROUP_ERROR;
7342}
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00007343
Bram Moolenaar071d4272004-06-13 20:20:40 +00007344/*
7345 * ":augroup {name}".
7346 */
7347 void
7348do_augroup(arg, del_group)
7349 char_u *arg;
7350 int del_group;
7351{
7352 int i;
7353
7354 if (del_group)
7355 {
7356 if (*arg == NUL)
7357 EMSG(_(e_argreq));
7358 else
7359 au_del_group(arg);
7360 }
7361 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
7362 current_augroup = AUGROUP_DEFAULT;
7363 else if (*arg) /* ":aug xxx": switch to group xxx */
7364 {
7365 i = au_new_group(arg);
7366 if (i != AUGROUP_ERROR)
7367 current_augroup = i;
7368 }
7369 else /* ":aug": list the group names */
7370 {
7371 msg_start();
7372 for (i = 0; i < augroups.ga_len; ++i)
7373 {
7374 if (AUGROUP_NAME(i) != NULL)
7375 {
7376 msg_puts(AUGROUP_NAME(i));
7377 msg_puts((char_u *)" ");
7378 }
7379 }
7380 msg_clr_eos();
7381 msg_end();
7382 }
7383}
7384
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007385#if defined(EXITFREE) || defined(PROTO)
7386 void
7387free_all_autocmds()
7388{
7389 for (current_augroup = -1; current_augroup < augroups.ga_len;
7390 ++current_augroup)
7391 do_autocmd((char_u *)"", TRUE);
7392 ga_clear_strings(&augroups);
7393}
7394#endif
7395
Bram Moolenaar071d4272004-06-13 20:20:40 +00007396/*
7397 * Return the event number for event name "start".
7398 * Return NUM_EVENTS if the event name was not found.
7399 * Return a pointer to the next event name in "end".
7400 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007401 static event_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00007402event_name2nr(start, end)
7403 char_u *start;
7404 char_u **end;
7405{
7406 char_u *p;
7407 int i;
7408 int len;
7409
7410 /* the event name ends with end of line, a blank or a comma */
7411 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7412 ;
7413 for (i = 0; event_names[i].name != NULL; ++i)
7414 {
7415 len = (int)STRLEN(event_names[i].name);
7416 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7417 break;
7418 }
7419 if (*p == ',')
7420 ++p;
7421 *end = p;
7422 if (event_names[i].name == NULL)
7423 return NUM_EVENTS;
7424 return event_names[i].event;
7425}
7426
7427/*
7428 * Return the name for event "event".
7429 */
7430 static char_u *
7431event_nr2name(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007432 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007433{
7434 int i;
7435
7436 for (i = 0; event_names[i].name != NULL; ++i)
7437 if (event_names[i].event == event)
7438 return (char_u *)event_names[i].name;
7439 return (char_u *)"Unknown";
7440}
7441
7442/*
7443 * Scan over the events. "*" stands for all events.
7444 */
7445 static char_u *
7446find_end_event(arg, have_group)
7447 char_u *arg;
7448 int have_group; /* TRUE when group name was found */
7449{
7450 char_u *pat;
7451 char_u *p;
7452
7453 if (*arg == '*')
7454 {
7455 if (arg[1] && !vim_iswhite(arg[1]))
7456 {
7457 EMSG2(_("E215: Illegal character after *: %s"), arg);
7458 return NULL;
7459 }
7460 pat = arg + 1;
7461 }
7462 else
7463 {
7464 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7465 {
7466 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7467 {
7468 if (have_group)
7469 EMSG2(_("E216: No such event: %s"), pat);
7470 else
7471 EMSG2(_("E216: No such group or event: %s"), pat);
7472 return NULL;
7473 }
7474 }
7475 }
7476 return pat;
7477}
7478
7479/*
7480 * Return TRUE if "event" is included in 'eventignore'.
7481 */
7482 static int
7483event_ignored(event)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007484 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007485{
7486 char_u *p = p_ei;
7487
7488 if (STRICMP(p_ei, "all") == 0)
7489 return TRUE;
7490
7491 while (*p)
7492 if (event_name2nr(p, &p) == event)
7493 return TRUE;
7494
7495 return FALSE;
7496}
7497
7498/*
7499 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7500 */
7501 int
7502check_ei()
7503{
7504 char_u *p = p_ei;
7505
7506 if (STRICMP(p_ei, "all") == 0)
7507 return OK;
7508
7509 while (*p)
7510 if (event_name2nr(p, &p) == NUM_EVENTS)
7511 return FAIL;
7512
7513 return OK;
7514}
7515
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007516# if defined(FEAT_SYN_HL) || defined(PROTO)
7517
7518/*
7519 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7520 * buffer loaded into the window. "what" must start with a comma.
7521 * Returns the old value of 'eventignore' in allocated memory.
7522 */
7523 char_u *
7524au_event_disable(what)
7525 char *what;
7526{
7527 char_u *new_ei;
7528 char_u *save_ei;
7529
7530 save_ei = vim_strsave(p_ei);
7531 if (save_ei != NULL)
7532 {
Bram Moolenaara5792f52005-11-23 21:25:05 +00007533 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007534 if (new_ei != NULL)
7535 {
7536 STRCAT(new_ei, what);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007537 set_string_option_direct((char_u *)"ei", -1, new_ei,
7538 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007539 vim_free(new_ei);
7540 }
7541 }
7542 return save_ei;
7543}
7544
7545 void
7546au_event_restore(old_ei)
7547 char_u *old_ei;
7548{
7549 if (old_ei != NULL)
7550 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007551 set_string_option_direct((char_u *)"ei", -1, old_ei,
7552 OPT_FREE, SID_NONE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007553 vim_free(old_ei);
7554 }
7555}
7556# endif /* FEAT_SYN_HL */
7557
Bram Moolenaar071d4272004-06-13 20:20:40 +00007558/*
7559 * do_autocmd() -- implements the :autocmd command. Can be used in the
7560 * following ways:
7561 *
7562 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7563 * will be automatically executed for <event>
7564 * when editing a file matching <pat>, in
7565 * the current group.
7566 * :autocmd <event> <pat> Show the auto-commands associated with
7567 * <event> and <pat>.
7568 * :autocmd <event> Show the auto-commands associated with
7569 * <event>.
7570 * :autocmd Show all auto-commands.
7571 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7572 * <event> and <pat>, and add the command
7573 * <cmd>, for the current group.
7574 * :autocmd! <event> <pat> Remove all auto-commands associated with
7575 * <event> and <pat> for the current group.
7576 * :autocmd! <event> Remove all auto-commands associated with
7577 * <event> for the current group.
7578 * :autocmd! Remove ALL auto-commands for the current
7579 * group.
7580 *
7581 * Multiple events and patterns may be given separated by commas. Here are
7582 * some examples:
7583 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7584 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7585 *
7586 * :autocmd * *.c show all autocommands for *.c files.
Bram Moolenaard35f9712005-12-18 22:02:33 +00007587 *
7588 * Mostly a {group} argument can optionally appear before <event>.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007589 */
7590 void
7591do_autocmd(arg, forceit)
7592 char_u *arg;
7593 int forceit;
7594{
7595 char_u *pat;
7596 char_u *envpat = NULL;
7597 char_u *cmd;
Bram Moolenaar754b5602006-02-09 23:53:20 +00007598 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007599 int need_free = FALSE;
7600 int nested = FALSE;
7601 int group;
7602
7603 /*
7604 * Check for a legal group name. If not, use AUGROUP_ALL.
7605 */
7606 group = au_get_grouparg(&arg);
7607 if (arg == NULL) /* out of memory */
7608 return;
7609
7610 /*
7611 * Scan over the events.
7612 * If we find an illegal name, return here, don't do anything.
7613 */
7614 pat = find_end_event(arg, group != AUGROUP_ALL);
7615 if (pat == NULL)
7616 return;
7617
7618 /*
7619 * Scan over the pattern. Put a NUL at the end.
7620 */
7621 pat = skipwhite(pat);
7622 cmd = pat;
7623 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7624 cmd++;
7625 if (*cmd)
7626 *cmd++ = NUL;
7627
7628 /* Expand environment variables in the pattern. Set 'shellslash', we want
7629 * forward slashes here. */
7630 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7631 {
7632#ifdef BACKSLASH_IN_FILENAME
7633 int p_ssl_save = p_ssl;
7634
7635 p_ssl = TRUE;
7636#endif
7637 envpat = expand_env_save(pat);
7638#ifdef BACKSLASH_IN_FILENAME
7639 p_ssl = p_ssl_save;
7640#endif
7641 if (envpat != NULL)
7642 pat = envpat;
7643 }
7644
7645 /*
7646 * Check for "nested" flag.
7647 */
7648 cmd = skipwhite(cmd);
7649 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7650 {
7651 nested = TRUE;
7652 cmd = skipwhite(cmd + 6);
7653 }
7654
7655 /*
7656 * Find the start of the commands.
7657 * Expand <sfile> in it.
7658 */
7659 if (*cmd != NUL)
7660 {
7661 cmd = expand_sfile(cmd);
7662 if (cmd == NULL) /* some error */
7663 return;
7664 need_free = TRUE;
7665 }
7666
7667 /*
7668 * Print header when showing autocommands.
7669 */
7670 if (!forceit && *cmd == NUL)
7671 {
7672 /* Highlight title */
7673 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7674 }
7675
7676 /*
7677 * Loop over the events.
7678 */
Bram Moolenaar754b5602006-02-09 23:53:20 +00007679 last_event = (event_T)-1; /* for listing the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007680 last_group = AUGROUP_ERROR; /* for listing the group name */
7681 if (*arg == '*' || *arg == NUL)
7682 {
Bram Moolenaar754b5602006-02-09 23:53:20 +00007683 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
7684 event = (event_T)((int)event + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007685 if (do_autocmd_event(event, pat,
7686 nested, cmd, forceit, group) == FAIL)
7687 break;
7688 }
7689 else
7690 {
7691 while (*arg && !vim_iswhite(*arg))
7692 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7693 nested, cmd, forceit, group) == FAIL)
7694 break;
7695 }
7696
7697 if (need_free)
7698 vim_free(cmd);
7699 vim_free(envpat);
7700}
7701
7702/*
7703 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7704 * The "argp" argument is advanced to the following argument.
7705 *
7706 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7707 */
7708 static int
7709au_get_grouparg(argp)
7710 char_u **argp;
7711{
7712 char_u *group_name;
7713 char_u *p;
7714 char_u *arg = *argp;
7715 int group = AUGROUP_ALL;
7716
7717 p = skiptowhite(arg);
7718 if (p > arg)
7719 {
7720 group_name = vim_strnsave(arg, (int)(p - arg));
7721 if (group_name == NULL) /* out of memory */
7722 return AUGROUP_ERROR;
7723 group = au_find_group(group_name);
7724 if (group == AUGROUP_ERROR)
7725 group = AUGROUP_ALL; /* no match, use all groups */
7726 else
7727 *argp = skipwhite(p); /* match, skip over group name */
7728 vim_free(group_name);
7729 }
7730 return group;
7731}
7732
7733/*
7734 * do_autocmd() for one event.
7735 * If *pat == NUL do for all patterns.
7736 * If *cmd == NUL show entries.
7737 * If forceit == TRUE delete entries.
7738 * If group is not AUGROUP_ALL, only use this group.
7739 */
7740 static int
7741do_autocmd_event(event, pat, nested, cmd, forceit, group)
Bram Moolenaar754b5602006-02-09 23:53:20 +00007742 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007743 char_u *pat;
7744 int nested;
7745 char_u *cmd;
7746 int forceit;
7747 int group;
7748{
7749 AutoPat *ap;
7750 AutoPat **prev_ap;
7751 AutoCmd *ac;
7752 AutoCmd **prev_ac;
7753 int brace_level;
7754 char_u *endpat;
7755 int findgroup;
7756 int allgroups;
7757 int patlen;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007758 int is_buflocal;
7759 int buflocal_nr;
7760 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007761
7762 if (group == AUGROUP_ALL)
7763 findgroup = current_augroup;
7764 else
7765 findgroup = group;
7766 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7767
7768 /*
7769 * Show or delete all patterns for an event.
7770 */
7771 if (*pat == NUL)
7772 {
7773 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7774 {
7775 if (forceit) /* delete the AutoPat, if it's in the current group */
7776 {
7777 if (ap->group == findgroup)
7778 au_remove_pat(ap);
7779 }
7780 else if (group == AUGROUP_ALL || ap->group == group)
7781 show_autocmd(ap, event);
7782 }
7783 }
7784
7785 /*
7786 * Loop through all the specified patterns.
7787 */
7788 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7789 {
7790 /*
7791 * Find end of the pattern.
7792 * Watch out for a comma in braces, like "*.\{obj,o\}".
7793 */
7794 brace_level = 0;
7795 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7796 || endpat[-1] == '\\'); ++endpat)
7797 {
7798 if (*endpat == '{')
7799 brace_level++;
7800 else if (*endpat == '}')
7801 brace_level--;
7802 }
7803 if (pat == endpat) /* ignore single comma */
7804 continue;
7805 patlen = (int)(endpat - pat);
7806
7807 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007808 * detect special <buflocal[=X]> buffer-local patterns
7809 */
7810 is_buflocal = FALSE;
7811 buflocal_nr = 0;
7812
7813 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
7814 && pat[patlen - 1] == '>')
7815 {
7816 /* Error will be printed only for addition. printing and removing
7817 * will proceed silently. */
7818 is_buflocal = TRUE;
7819 if (patlen == 8)
7820 buflocal_nr = curbuf->b_fnum;
7821 else if (patlen > 9 && pat[7] == '=')
7822 {
7823 /* <buffer=abuf> */
7824 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
7825 buflocal_nr = autocmd_bufnr;
7826 /* <buffer=123> */
7827 else if (skipdigits(pat + 8) == pat + patlen - 1)
7828 buflocal_nr = atoi((char *)pat + 8);
7829 }
7830 }
7831
7832 if (is_buflocal)
7833 {
7834 /* normalize pat into standard "<buffer>#N" form */
7835 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
7836 pat = buflocal_pat; /* can modify pat and patlen */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007837 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007838 }
7839
7840 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007841 * Find AutoPat entries with this pattern.
7842 */
7843 prev_ap = &first_autopat[(int)event];
7844 while ((ap = *prev_ap) != NULL)
7845 {
7846 if (ap->pat != NULL)
7847 {
7848 /* Accept a pattern when:
7849 * - a group was specified and it's that group, or a group was
7850 * not specified and it's the current group, or a group was
7851 * not specified and we are listing
7852 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007853 * - the pattern matches.
7854 * For <buffer[=X]>, this condition works because we normalize
7855 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007856 */
7857 if ((allgroups || ap->group == findgroup)
7858 && ap->patlen == patlen
7859 && STRNCMP(pat, ap->pat, patlen) == 0)
7860 {
7861 /*
7862 * Remove existing autocommands.
7863 * If adding any new autocmd's for this AutoPat, don't
7864 * delete the pattern from the autopat list, append to
7865 * this list.
7866 */
7867 if (forceit)
7868 {
7869 if (*cmd != NUL && ap->next == NULL)
7870 {
7871 au_remove_cmds(ap);
7872 break;
7873 }
7874 au_remove_pat(ap);
7875 }
7876
7877 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007878 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00007879 */
7880 else if (*cmd == NUL)
7881 show_autocmd(ap, event);
7882
7883 /*
7884 * Add autocmd to this autopat, if it's the last one.
7885 */
7886 else if (ap->next == NULL)
7887 break;
7888 }
7889 }
7890 prev_ap = &ap->next;
7891 }
7892
7893 /*
7894 * Add a new command.
7895 */
7896 if (*cmd != NUL)
7897 {
7898 /*
7899 * If the pattern we want to add a command to does appear at the
7900 * end of the list (or not is not in the list at all), add the
7901 * pattern at the end of the list.
7902 */
7903 if (ap == NULL)
7904 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007905 /* refuse to add buffer-local ap if buffer number is invalid */
7906 if (is_buflocal && (buflocal_nr == 0
7907 || buflist_findnr(buflocal_nr) == NULL))
7908 {
7909 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
7910 buflocal_nr);
7911 return FAIL;
7912 }
7913
Bram Moolenaar071d4272004-06-13 20:20:40 +00007914 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7915 if (ap == NULL)
7916 return FAIL;
7917 ap->pat = vim_strnsave(pat, patlen);
7918 ap->patlen = patlen;
7919 if (ap->pat == NULL)
7920 {
7921 vim_free(ap);
7922 return FAIL;
7923 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007924
7925 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007926 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007927 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007928 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007929 }
7930 else
7931 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00007932 char_u *reg_pat;
7933
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007934 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007935 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007936 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007937 if (reg_pat != NULL)
7938 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00007939 vim_free(reg_pat);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007940 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007941 {
7942 vim_free(ap->pat);
7943 vim_free(ap);
7944 return FAIL;
7945 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007946 }
7947 ap->cmds = NULL;
7948 *prev_ap = ap;
7949 ap->next = NULL;
7950 if (group == AUGROUP_ALL)
7951 ap->group = current_augroup;
7952 else
7953 ap->group = group;
7954 }
7955
7956 /*
7957 * Add the autocmd at the end of the AutoCmd list.
7958 */
7959 prev_ac = &(ap->cmds);
7960 while ((ac = *prev_ac) != NULL)
7961 prev_ac = &ac->next;
7962 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7963 if (ac == NULL)
7964 return FAIL;
7965 ac->cmd = vim_strsave(cmd);
7966#ifdef FEAT_EVAL
7967 ac->scriptID = current_SID;
7968#endif
7969 if (ac->cmd == NULL)
7970 {
7971 vim_free(ac);
7972 return FAIL;
7973 }
7974 ac->next = NULL;
7975 *prev_ac = ac;
7976 ac->nested = nested;
7977 }
7978 }
7979
7980 au_cleanup(); /* may really delete removed patterns/commands now */
7981 return OK;
7982}
7983
7984/*
7985 * Implementation of ":doautocmd [group] event [fname]".
7986 * Return OK for success, FAIL for failure;
7987 */
7988 int
7989do_doautocmd(arg, do_msg)
7990 char_u *arg;
7991 int do_msg; /* give message for no matching autocmds? */
7992{
7993 char_u *fname;
7994 int nothing_done = TRUE;
7995 int group;
7996
7997 /*
7998 * Check for a legal group name. If not, use AUGROUP_ALL.
7999 */
8000 group = au_get_grouparg(&arg);
8001 if (arg == NULL) /* out of memory */
8002 return FAIL;
8003
8004 if (*arg == '*')
8005 {
8006 EMSG(_("E217: Can't execute autocommands for ALL events"));
8007 return FAIL;
8008 }
8009
8010 /*
8011 * Scan over the events.
8012 * If we find an illegal name, return here, don't do anything.
8013 */
8014 fname = find_end_event(arg, group != AUGROUP_ALL);
8015 if (fname == NULL)
8016 return FAIL;
8017
8018 fname = skipwhite(fname);
8019
8020 /*
8021 * Loop over the events.
8022 */
8023 while (*arg && !vim_iswhite(*arg))
8024 if (apply_autocmds_group(event_name2nr(arg, &arg),
8025 fname, NULL, TRUE, group, curbuf, NULL))
8026 nothing_done = FALSE;
8027
8028 if (nothing_done && do_msg)
8029 MSG(_("No matching autocommands"));
8030
8031#ifdef FEAT_EVAL
8032 return aborting() ? FAIL : OK;
8033#else
8034 return OK;
8035#endif
8036}
8037
8038/*
8039 * ":doautoall": execute autocommands for each loaded buffer.
8040 */
8041 void
8042ex_doautoall(eap)
8043 exarg_T *eap;
8044{
8045 int retval;
8046 aco_save_T aco;
8047 buf_T *buf;
8048
8049 /*
8050 * This is a bit tricky: For some commands curwin->w_buffer needs to be
8051 * equal to curbuf, but for some buffers there may not be a window.
8052 * So we change the buffer for the current window for a moment. This
8053 * gives problems when the autocommands make changes to the list of
8054 * buffers or windows...
8055 */
8056 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
8057 {
8058 if (curbuf->b_ml.ml_mfp != NULL)
8059 {
8060 /* find a window for this buffer and save some values */
8061 aucmd_prepbuf(&aco, buf);
8062
8063 /* execute the autocommands for this buffer */
8064 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaara3227e22006-03-08 21:32:40 +00008065 do_modelines(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008066
8067 /* restore the current window */
8068 aucmd_restbuf(&aco);
8069
8070 /* stop if there is some error or buffer was deleted */
8071 if (retval == FAIL || !buf_valid(buf))
8072 break;
8073 }
8074 }
8075
8076 check_cursor(); /* just in case lines got deleted */
8077}
8078
8079/*
8080 * Prepare for executing autocommands for (hidden) buffer "buf".
8081 * Search a window for the current buffer. Save the cursor position and
8082 * screen offset.
8083 * Set "curbuf" and "curwin" to match "buf".
8084 */
8085 void
8086aucmd_prepbuf(aco, buf)
8087 aco_save_T *aco; /* structure to save values in */
8088 buf_T *buf; /* new curbuf */
8089{
8090 win_T *win;
8091
8092 aco->new_curbuf = buf;
8093
8094 /* Find a window that is for the new buffer */
8095 if (buf == curbuf) /* be quick when buf is curbuf */
8096 win = curwin;
8097 else
8098#ifdef FEAT_WINDOWS
8099 for (win = firstwin; win != NULL; win = win->w_next)
8100 if (win->w_buffer == buf)
8101 break;
8102#else
8103 win = NULL;
8104#endif
8105
8106 /*
8107 * Prefer to use an existing window for the buffer, it has the least side
8108 * effects (esp. if "buf" is curbuf).
8109 * Otherwise, use curwin for "buf". It might make some items in the
8110 * window invalid. At least save the cursor and topline.
8111 */
8112 if (win != NULL)
8113 {
8114 /* there is a window for "buf", make it the curwin */
8115 aco->save_curwin = curwin;
8116 curwin = win;
8117 aco->save_buf = win->w_buffer;
8118 aco->new_curwin = win;
8119 }
8120 else
8121 {
8122 /* there is no window for "buf", use curwin */
8123 aco->save_curwin = NULL;
8124 aco->save_buf = curbuf;
8125 --curbuf->b_nwindows;
8126 curwin->w_buffer = buf;
8127 ++buf->b_nwindows;
8128
8129 /* save cursor and topline, set them to safe values */
8130 aco->save_cursor = curwin->w_cursor;
8131 curwin->w_cursor.lnum = 1;
8132 curwin->w_cursor.col = 0;
8133 aco->save_topline = curwin->w_topline;
8134 curwin->w_topline = 1;
8135#ifdef FEAT_DIFF
8136 aco->save_topfill = curwin->w_topfill;
8137 curwin->w_topfill = 0;
8138#endif
8139 }
8140
8141 curbuf = buf;
8142}
8143
8144/*
8145 * Cleanup after executing autocommands for a (hidden) buffer.
8146 * Restore the window as it was (if possible).
8147 */
8148 void
8149aucmd_restbuf(aco)
8150 aco_save_T *aco; /* structure holding saved values */
8151{
8152 if (aco->save_curwin != NULL)
8153 {
8154 /* restore curwin */
8155#ifdef FEAT_WINDOWS
8156 if (win_valid(aco->save_curwin))
8157#endif
8158 {
8159 /* restore the buffer which was previously edited by curwin, if
8160 * it's still the same window and it's valid */
8161 if (curwin == aco->new_curwin
8162 && buf_valid(aco->save_buf)
8163 && aco->save_buf->b_ml.ml_mfp != NULL)
8164 {
8165 --curbuf->b_nwindows;
8166 curbuf = aco->save_buf;
8167 curwin->w_buffer = curbuf;
8168 ++curbuf->b_nwindows;
8169 }
8170
8171 curwin = aco->save_curwin;
8172 curbuf = curwin->w_buffer;
8173 }
8174 }
8175 else
8176 {
8177 /* restore buffer for curwin if it still exists and is loaded */
8178 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
8179 {
8180 --curbuf->b_nwindows;
8181 curbuf = aco->save_buf;
8182 curwin->w_buffer = curbuf;
8183 ++curbuf->b_nwindows;
8184 curwin->w_cursor = aco->save_cursor;
8185 check_cursor();
8186 /* check topline < line_count, in case lines got deleted */
8187 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
8188 {
8189 curwin->w_topline = aco->save_topline;
8190#ifdef FEAT_DIFF
8191 curwin->w_topfill = aco->save_topfill;
8192#endif
8193 }
8194 else
8195 {
8196 curwin->w_topline = curbuf->b_ml.ml_line_count;
8197#ifdef FEAT_DIFF
8198 curwin->w_topfill = 0;
8199#endif
8200 }
8201 }
8202 }
8203}
8204
8205static int autocmd_nested = FALSE;
8206
8207/*
8208 * Execute autocommands for "event" and file name "fname".
8209 * Return TRUE if some commands were executed.
8210 */
8211 int
8212apply_autocmds(event, fname, fname_io, force, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008213 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008214 char_u *fname; /* NULL or empty means use actual file name */
8215 char_u *fname_io; /* fname to use for <afile> on cmdline */
8216 int force; /* when TRUE, ignore autocmd_busy */
8217 buf_T *buf; /* buffer for <abuf> */
8218{
8219 return apply_autocmds_group(event, fname, fname_io, force,
8220 AUGROUP_ALL, buf, NULL);
8221}
8222
8223/*
8224 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
8225 * setting v:filearg.
8226 */
8227 static int
8228apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008229 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008230 char_u *fname;
8231 char_u *fname_io;
8232 int force;
8233 buf_T *buf;
8234 exarg_T *eap;
8235{
8236 return apply_autocmds_group(event, fname, fname_io, force,
8237 AUGROUP_ALL, buf, eap);
8238}
8239
8240/*
8241 * Like apply_autocmds(), but handles the caller's retval. If the script
8242 * processing is being aborted or if retval is FAIL when inside a try
8243 * conditional, no autocommands are executed. If otherwise the autocommands
8244 * cause the script to be aborted, retval is set to FAIL.
8245 */
8246 int
8247apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008248 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008249 char_u *fname; /* NULL or empty means use actual file name */
8250 char_u *fname_io; /* fname to use for <afile> on cmdline */
8251 int force; /* when TRUE, ignore autocmd_busy */
8252 buf_T *buf; /* buffer for <abuf> */
8253 int *retval; /* pointer to caller's retval */
8254{
8255 int did_cmd;
8256
Bram Moolenaar1e015462005-09-25 22:16:38 +00008257#ifdef FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008258 if (should_abort(*retval))
8259 return FALSE;
Bram Moolenaar1e015462005-09-25 22:16:38 +00008260#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008261
8262 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
8263 AUGROUP_ALL, buf, NULL);
Bram Moolenaar1e015462005-09-25 22:16:38 +00008264 if (did_cmd
8265#ifdef FEAT_EVAL
8266 && aborting()
8267#endif
8268 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00008269 *retval = FAIL;
8270 return did_cmd;
8271}
8272
Bram Moolenaard35f9712005-12-18 22:02:33 +00008273/*
8274 * Return TRUE when there is a CursorHold autocommand defined.
8275 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008276 int
8277has_cursorhold()
8278{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008279 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
8280 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008281}
Bram Moolenaard35f9712005-12-18 22:02:33 +00008282
8283/*
8284 * Return TRUE if the CursorHold event can be triggered.
8285 */
8286 int
8287trigger_cursorhold()
8288{
Bram Moolenaar754b5602006-02-09 23:53:20 +00008289 int state;
8290
8291 if (!did_cursorhold && has_cursorhold() && !Recording)
8292 {
8293 state = get_real_state();
8294 if (state == NORMAL_BUSY || (state & INSERT) != 0)
8295 return TRUE;
8296 }
8297 return FALSE;
Bram Moolenaard35f9712005-12-18 22:02:33 +00008298}
Bram Moolenaar754b5602006-02-09 23:53:20 +00008299
8300/*
8301 * Return TRUE when there is a CursorMoved autocommand defined.
8302 */
8303 int
8304has_cursormoved()
8305{
8306 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
8307}
8308
8309/*
8310 * Return TRUE when there is a CursorMovedI autocommand defined.
8311 */
8312 int
8313has_cursormovedI()
8314{
8315 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
8316}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008317
8318 static int
8319apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008320 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008321 char_u *fname; /* NULL or empty means use actual file name */
8322 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
8323 use fname */
8324 int force; /* when TRUE, ignore autocmd_busy */
8325 int group; /* group ID, or AUGROUP_ALL */
8326 buf_T *buf; /* buffer for <abuf> */
8327 exarg_T *eap; /* command arguments */
8328{
8329 char_u *sfname = NULL; /* short file name */
8330 char_u *tail;
8331 int save_changed;
8332 buf_T *old_curbuf;
8333 int retval = FALSE;
8334 char_u *save_sourcing_name;
8335 linenr_T save_sourcing_lnum;
8336 char_u *save_autocmd_fname;
8337 int save_autocmd_bufnr;
8338 char_u *save_autocmd_match;
8339 int save_autocmd_busy;
8340 int save_autocmd_nested;
8341 static int nesting = 0;
8342 AutoPatCmd patcmd;
8343 AutoPat *ap;
8344#ifdef FEAT_EVAL
8345 scid_T save_current_SID;
8346 void *save_funccalp;
8347 char_u *save_cmdarg;
8348 long save_cmdbang;
8349#endif
8350 static int filechangeshell_busy = FALSE;
Bram Moolenaar05159a02005-02-26 23:04:13 +00008351#ifdef FEAT_PROFILE
8352 proftime_T wait_time;
8353#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008354
8355 /*
8356 * Quickly return if there are no autocommands for this event or
8357 * autocommands are blocked.
8358 */
8359 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008360 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008361
8362 /*
8363 * When autocommands are busy, new autocommands are only executed when
8364 * explicitly enabled with the "nested" flag.
8365 */
8366 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008367 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008368
8369#ifdef FEAT_EVAL
8370 /*
8371 * Quickly return when immdediately aborting on error, or when an interrupt
8372 * occurred or an exception was thrown but not caught.
8373 */
8374 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008375 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008376#endif
8377
8378 /*
8379 * FileChangedShell never nests, because it can create an endless loop.
8380 */
Bram Moolenaar56718732006-03-15 22:53:57 +00008381 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
8382 || event == EVENT_FILECHANGEDSHELLPOST))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008383 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008384
8385 /*
8386 * Ignore events in 'eventignore'.
8387 */
8388 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008389 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008390
8391 /*
8392 * Allow nesting of autocommands, but restrict the depth, because it's
8393 * possible to create an endless loop.
8394 */
8395 if (nesting == 10)
8396 {
8397 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008398 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008399 }
8400
8401 /*
8402 * Check if these autocommands are disabled. Used when doing ":all" or
8403 * ":ball".
8404 */
8405 if ( (autocmd_no_enter
8406 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
8407 || (autocmd_no_leave
8408 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008409 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008410
8411 /*
8412 * Save the autocmd_* variables and info about the current buffer.
8413 */
8414 save_autocmd_fname = autocmd_fname;
8415 save_autocmd_bufnr = autocmd_bufnr;
8416 save_autocmd_match = autocmd_match;
8417 save_autocmd_busy = autocmd_busy;
8418 save_autocmd_nested = autocmd_nested;
8419 save_changed = curbuf->b_changed;
8420 old_curbuf = curbuf;
8421
8422 /*
8423 * Set the file name to be used for <afile>.
8424 */
8425 if (fname_io == NULL)
8426 {
8427 if (fname != NULL && *fname != NUL)
8428 autocmd_fname = fname;
8429 else if (buf != NULL)
8430 autocmd_fname = buf->b_fname;
8431 else
8432 autocmd_fname = NULL;
8433 }
8434 else
8435 autocmd_fname = fname_io;
8436
8437 /*
8438 * Set the buffer number to be used for <abuf>.
8439 */
8440 if (buf == NULL)
8441 autocmd_bufnr = 0;
8442 else
8443 autocmd_bufnr = buf->b_fnum;
8444
8445 /*
8446 * When the file name is NULL or empty, use the file name of buffer "buf".
8447 * Always use the full path of the file name to match with, in case
8448 * "allow_dirs" is set.
8449 */
8450 if (fname == NULL || *fname == NUL)
8451 {
8452 if (buf == NULL)
8453 fname = NULL;
8454 else
8455 {
8456#ifdef FEAT_SYN_HL
8457 if (event == EVENT_SYNTAX)
8458 fname = buf->b_p_syn;
8459 else
8460#endif
8461 if (event == EVENT_FILETYPE)
8462 fname = buf->b_p_ft;
8463 else
8464 {
8465 if (buf->b_sfname != NULL)
8466 sfname = vim_strsave(buf->b_sfname);
8467 fname = buf->b_ffname;
8468 }
8469 }
8470 if (fname == NULL)
8471 fname = (char_u *)"";
8472 fname = vim_strsave(fname); /* make a copy, so we can change it */
8473 }
8474 else
8475 {
8476 sfname = vim_strsave(fname);
Bram Moolenaar7c626922005-02-07 22:01:03 +00008477 /* Don't try expanding FileType, Syntax, WindowID or QuickFixCmd* */
8478 if (event == EVENT_FILETYPE
8479 || event == EVENT_SYNTAX
8480 || event == EVENT_REMOTEREPLY
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00008481 || event == EVENT_SPELLFILEMISSING
Bram Moolenaar7c626922005-02-07 22:01:03 +00008482 || event == EVENT_QUICKFIXCMDPRE
8483 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008484 fname = vim_strsave(fname);
8485 else
8486 fname = FullName_save(fname, FALSE);
8487 }
8488 if (fname == NULL) /* out of memory */
8489 {
8490 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008491 retval = FALSE;
8492 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008493 }
8494
8495#ifdef BACKSLASH_IN_FILENAME
8496 /*
8497 * Replace all backslashes with forward slashes. This makes the
8498 * autocommand patterns portable between Unix and MS-DOS.
8499 */
8500 if (sfname != NULL)
8501 forward_slash(sfname);
8502 forward_slash(fname);
8503#endif
8504
8505#ifdef VMS
8506 /* remove version for correct match */
8507 if (sfname != NULL)
8508 vms_remove_version(sfname);
8509 vms_remove_version(fname);
8510#endif
8511
8512 /*
8513 * Set the name to be used for <amatch>.
8514 */
8515 autocmd_match = fname;
8516
8517
8518 /* Don't redraw while doing auto commands. */
8519 ++RedrawingDisabled;
8520 save_sourcing_name = sourcing_name;
8521 sourcing_name = NULL; /* don't free this one */
8522 save_sourcing_lnum = sourcing_lnum;
8523 sourcing_lnum = 0; /* no line number here */
8524
8525#ifdef FEAT_EVAL
8526 save_current_SID = current_SID;
8527
Bram Moolenaar05159a02005-02-26 23:04:13 +00008528# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00008529 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00008530 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
8531# endif
8532
Bram Moolenaar071d4272004-06-13 20:20:40 +00008533 /* Don't use local function variables, if called from a function */
8534 save_funccalp = save_funccal();
8535#endif
8536
8537 /*
8538 * When starting to execute autocommands, save the search patterns.
8539 */
8540 if (!autocmd_busy)
8541 {
8542 save_search_patterns();
8543 saveRedobuff();
8544 did_filetype = keep_filetype;
8545 }
8546
8547 /*
8548 * Note that we are applying autocmds. Some commands need to know.
8549 */
8550 autocmd_busy = TRUE;
8551 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
8552 ++nesting; /* see matching decrement below */
8553
8554 /* Remember that FileType was triggered. Used for did_filetype(). */
8555 if (event == EVENT_FILETYPE)
8556 did_filetype = TRUE;
8557
8558 tail = gettail(fname);
8559
8560 /* Find first autocommand that matches */
8561 patcmd.curpat = first_autopat[(int)event];
8562 patcmd.nextcmd = NULL;
8563 patcmd.group = group;
8564 patcmd.fname = fname;
8565 patcmd.sfname = sfname;
8566 patcmd.tail = tail;
8567 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008568 patcmd.arg_bufnr = autocmd_bufnr;
8569 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008570 auto_next_pat(&patcmd, FALSE);
8571
8572 /* found one, start executing the autocommands */
8573 if (patcmd.curpat != NULL)
8574 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008575 /* add to active_apc_list */
8576 patcmd.next = active_apc_list;
8577 active_apc_list = &patcmd;
8578
Bram Moolenaar071d4272004-06-13 20:20:40 +00008579#ifdef FEAT_EVAL
8580 /* set v:cmdarg (only when there is a matching pattern) */
8581 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
8582 if (eap != NULL)
8583 {
8584 save_cmdarg = set_cmdarg(eap, NULL);
8585 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
8586 }
8587 else
8588 save_cmdarg = NULL; /* avoid gcc warning */
8589#endif
8590 retval = TRUE;
8591 /* mark the last pattern, to avoid an endless loop when more patterns
8592 * are added when executing autocommands */
8593 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8594 ap->last = FALSE;
8595 ap->last = TRUE;
8596 check_lnums(TRUE); /* make sure cursor and topline are valid */
8597 do_cmdline(NULL, getnextac, (void *)&patcmd,
8598 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8599#ifdef FEAT_EVAL
8600 if (eap != NULL)
8601 {
8602 (void)set_cmdarg(NULL, save_cmdarg);
8603 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8604 }
8605#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008606 /* delete from active_apc_list */
8607 if (active_apc_list == &patcmd) /* just in case */
8608 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008609 }
8610
8611 --RedrawingDisabled;
8612 autocmd_busy = save_autocmd_busy;
8613 filechangeshell_busy = FALSE;
8614 autocmd_nested = save_autocmd_nested;
8615 vim_free(sourcing_name);
8616 sourcing_name = save_sourcing_name;
8617 sourcing_lnum = save_sourcing_lnum;
8618 autocmd_fname = save_autocmd_fname;
8619 autocmd_bufnr = save_autocmd_bufnr;
8620 autocmd_match = save_autocmd_match;
8621#ifdef FEAT_EVAL
8622 current_SID = save_current_SID;
8623 restore_funccal(save_funccalp);
Bram Moolenaar05159a02005-02-26 23:04:13 +00008624# ifdef FEAT_PROFILE
Bram Moolenaar371d5402006-03-20 21:47:49 +00008625 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +00008626 prof_child_exit(&wait_time);
8627# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008628#endif
8629 vim_free(fname);
8630 vim_free(sfname);
8631 --nesting; /* see matching increment above */
8632
8633 /*
8634 * When stopping to execute autocommands, restore the search patterns and
8635 * the redo buffer.
8636 */
8637 if (!autocmd_busy)
8638 {
8639 restore_search_patterns();
8640 restoreRedobuff();
8641 did_filetype = FALSE;
8642 }
8643
8644 /*
8645 * Some events don't set or reset the Changed flag.
8646 * Check if still in the same buffer!
8647 */
8648 if (curbuf == old_curbuf
8649 && (event == EVENT_BUFREADPOST
8650 || event == EVENT_BUFWRITEPOST
8651 || event == EVENT_FILEAPPENDPOST
8652 || event == EVENT_VIMLEAVE
8653 || event == EVENT_VIMLEAVEPRE))
8654 {
8655#ifdef FEAT_TITLE
8656 if (curbuf->b_changed != save_changed)
8657 need_maketitle = TRUE;
8658#endif
8659 curbuf->b_changed = save_changed;
8660 }
8661
8662 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008663
8664BYPASS_AU:
8665 /* When wiping out a buffer make sure all its buffer-local autocommands
8666 * are deleted. */
8667 if (event == EVENT_BUFWIPEOUT && buf != NULL)
8668 aubuflocal_remove(buf);
8669
Bram Moolenaar071d4272004-06-13 20:20:40 +00008670 return retval;
8671}
8672
8673/*
8674 * Find next autocommand pattern that matches.
8675 */
8676 static void
8677auto_next_pat(apc, stop_at_last)
8678 AutoPatCmd *apc;
8679 int stop_at_last; /* stop when 'last' flag is set */
8680{
8681 AutoPat *ap;
8682 AutoCmd *cp;
8683 char_u *name;
8684 char *s;
8685
8686 vim_free(sourcing_name);
8687 sourcing_name = NULL;
8688
8689 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8690 {
8691 apc->curpat = NULL;
8692
8693 /* only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008694 * the group matches. For buffer-local autocommands only check the
8695 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008696 if (ap->pat != NULL && ap->cmds != NULL
8697 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8698 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008699 /* execution-condition */
8700 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008701 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
8702 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008703 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008704 {
8705 name = event_nr2name(apc->event);
8706 s = _("%s Auto commands for \"%s\"");
8707 sourcing_name = alloc((unsigned)(STRLEN(s)
8708 + STRLEN(name) + ap->patlen + 1));
8709 if (sourcing_name != NULL)
8710 {
8711 sprintf((char *)sourcing_name, s,
8712 (char *)name, (char *)ap->pat);
8713 if (p_verbose >= 8)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008714 {
8715 verbose_enter();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008716 smsg((char_u *)_("Executing %s"), sourcing_name);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008717 verbose_leave();
8718 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008719 }
8720
8721 apc->curpat = ap;
8722 apc->nextcmd = ap->cmds;
8723 /* mark last command */
8724 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8725 cp->last = FALSE;
8726 cp->last = TRUE;
8727 }
8728 line_breakcheck();
8729 if (apc->curpat != NULL) /* found a match */
8730 break;
8731 }
8732 if (stop_at_last && ap->last)
8733 break;
8734 }
8735}
8736
8737/*
8738 * Get next autocommand command.
8739 * Called by do_cmdline() to get the next line for ":if".
8740 * Returns allocated string, or NULL for end of autocommands.
8741 */
8742/* ARGSUSED */
8743 static char_u *
8744getnextac(c, cookie, indent)
8745 int c; /* not used */
8746 void *cookie;
8747 int indent; /* not used */
8748{
8749 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8750 char_u *retval;
8751 AutoCmd *ac;
8752
8753 /* Can be called again after returning the last line. */
8754 if (acp->curpat == NULL)
8755 return NULL;
8756
8757 /* repeat until we find an autocommand to execute */
8758 for (;;)
8759 {
8760 /* skip removed commands */
8761 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8762 if (acp->nextcmd->last)
8763 acp->nextcmd = NULL;
8764 else
8765 acp->nextcmd = acp->nextcmd->next;
8766
8767 if (acp->nextcmd != NULL)
8768 break;
8769
8770 /* at end of commands, find next pattern that matches */
8771 if (acp->curpat->last)
8772 acp->curpat = NULL;
8773 else
8774 acp->curpat = acp->curpat->next;
8775 if (acp->curpat != NULL)
8776 auto_next_pat(acp, TRUE);
8777 if (acp->curpat == NULL)
8778 return NULL;
8779 }
8780
8781 ac = acp->nextcmd;
8782
8783 if (p_verbose >= 9)
8784 {
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008785 verbose_enter_scroll();
Bram Moolenaar051b7822005-05-19 21:00:46 +00008786 smsg((char_u *)_("autocommand %s"), ac->cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008787 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaara04f10b2005-05-31 22:09:46 +00008788 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008789 }
8790 retval = vim_strsave(ac->cmd);
8791 autocmd_nested = ac->nested;
8792#ifdef FEAT_EVAL
8793 current_SID = ac->scriptID;
8794#endif
8795 if (ac->last)
8796 acp->nextcmd = NULL;
8797 else
8798 acp->nextcmd = ac->next;
8799 return retval;
8800}
8801
8802/*
8803 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008804 * To account for buffer-local autocommands, function needs to know
8805 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008806 */
8807 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008808has_autocmd(event, sfname, buf)
Bram Moolenaar754b5602006-02-09 23:53:20 +00008809 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008811 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008812{
8813 AutoPat *ap;
8814 char_u *fname;
8815 char_u *tail = gettail(sfname);
8816 int retval = FALSE;
8817
8818 fname = FullName_save(sfname, FALSE);
8819 if (fname == NULL)
8820 return FALSE;
8821
8822#ifdef BACKSLASH_IN_FILENAME
8823 /*
8824 * Replace all backslashes with forward slashes. This makes the
8825 * autocommand patterns portable between Unix and MS-DOS.
8826 */
8827 sfname = vim_strsave(sfname);
8828 if (sfname != NULL)
8829 forward_slash(sfname);
8830 forward_slash(fname);
8831#endif
8832
8833 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8834 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008835 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008836 ? match_file_pat(NULL, ap->reg_prog,
8837 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008838 : buf != NULL && ap->buflocal_nr == buf->b_fnum
8839 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008840 {
8841 retval = TRUE;
8842 break;
8843 }
8844
8845 vim_free(fname);
8846#ifdef BACKSLASH_IN_FILENAME
8847 vim_free(sfname);
8848#endif
8849
8850 return retval;
8851}
8852
8853#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8854/*
8855 * Function given to ExpandGeneric() to obtain the list of autocommand group
8856 * names.
8857 */
8858/*ARGSUSED*/
8859 char_u *
8860get_augroup_name(xp, idx)
8861 expand_T *xp;
8862 int idx;
8863{
8864 if (idx == augroups.ga_len) /* add "END" add the end */
8865 return (char_u *)"END";
8866 if (idx >= augroups.ga_len) /* end of list */
8867 return NULL;
8868 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8869 return (char_u *)"";
8870 return AUGROUP_NAME(idx); /* return a name */
8871}
8872
8873static int include_groups = FALSE;
8874
8875 char_u *
8876set_context_in_autocmd(xp, arg, doautocmd)
8877 expand_T *xp;
8878 char_u *arg;
8879 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8880{
8881 char_u *p;
8882 int group;
8883
8884 /* check for a group name, skip it if present */
8885 include_groups = FALSE;
8886 p = arg;
8887 group = au_get_grouparg(&arg);
8888 if (group == AUGROUP_ERROR)
8889 return NULL;
8890 /* If there only is a group name that's what we expand. */
8891 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8892 {
8893 arg = p;
8894 group = AUGROUP_ALL;
8895 }
8896
8897 /* skip over event name */
8898 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8899 if (*p == ',')
8900 arg = p + 1;
8901 if (*p == NUL)
8902 {
8903 if (group == AUGROUP_ALL)
8904 include_groups = TRUE;
8905 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8906 xp->xp_pattern = arg;
8907 return NULL;
8908 }
8909
8910 /* skip over pattern */
8911 arg = skipwhite(p);
8912 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8913 arg++;
8914 if (*arg)
8915 return arg; /* expand (next) command */
8916
8917 if (doautocmd)
8918 xp->xp_context = EXPAND_FILES; /* expand file names */
8919 else
8920 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8921 return NULL;
8922}
8923
8924/*
8925 * Function given to ExpandGeneric() to obtain the list of event names.
8926 */
8927/*ARGSUSED*/
8928 char_u *
8929get_event_name(xp, idx)
8930 expand_T *xp;
8931 int idx;
8932{
8933 if (idx < augroups.ga_len) /* First list group names, if wanted */
8934 {
8935 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8936 return (char_u *)""; /* skip deleted entries */
8937 return AUGROUP_NAME(idx); /* return a name */
8938 }
8939 return (char_u *)event_names[idx - augroups.ga_len].name;
8940}
8941
8942#endif /* FEAT_CMDL_COMPL */
8943
8944/*
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008945 * Return TRUE if autocmd is supported.
8946 */
8947 int
8948autocmd_supported(name)
8949 char_u *name;
8950{
8951 char_u *p;
8952
8953 return (event_name2nr(name, &p) != NUM_EVENTS);
8954}
8955
8956/*
Bram Moolenaar195d6352005-12-19 22:08:24 +00008957 * Return TRUE if an autocommand is defined for a group, event and
8958 * pattern: The group can be omitted to accept any group. "event" and "pattern"
8959 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
8960 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
8961 * Used for:
8962 * exists("#Group") or
8963 * exists("#Group#Event") or
8964 * exists("#Group#Event#pat") or
8965 * exists("#Event") or
8966 * exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00008967 */
8968 int
Bram Moolenaar195d6352005-12-19 22:08:24 +00008969au_exists(arg)
8970 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008971{
Bram Moolenaar195d6352005-12-19 22:08:24 +00008972 char_u *arg_save;
8973 char_u *pattern = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008974 char_u *event_name;
8975 char_u *p;
Bram Moolenaar754b5602006-02-09 23:53:20 +00008976 event_T event;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008977 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008978 buf_T *buflocal_buf = NULL;
Bram Moolenaar195d6352005-12-19 22:08:24 +00008979 int group;
8980 int retval = FALSE;
8981
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008982 /* Make a copy so that we can change the '#' chars to a NUL. */
Bram Moolenaar195d6352005-12-19 22:08:24 +00008983 arg_save = vim_strsave(arg);
8984 if (arg_save == NULL)
8985 return FALSE;
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008986 p = vim_strchr(arg_save, '#');
Bram Moolenaar195d6352005-12-19 22:08:24 +00008987 if (p != NULL)
8988 *p++ = NUL;
8989
8990 /* First, look for an autocmd group name */
8991 group = au_find_group(arg_save);
8992 if (group == AUGROUP_ERROR)
8993 {
8994 /* Didn't match a group name, assume the first argument is an event. */
8995 group = AUGROUP_ALL;
8996 event_name = arg_save;
8997 }
8998 else
8999 {
9000 if (p == NULL)
9001 {
9002 /* "Group": group name is present and it's recognized */
9003 retval = TRUE;
9004 goto theend;
9005 }
9006
9007 /* Must be "Group#Event" or "Group#Event#pat". */
9008 event_name = p;
9009 p = vim_strchr(event_name, '#');
9010 if (p != NULL)
9011 *p++ = NUL; /* "Group#Event#pat" */
9012 }
9013
9014 pattern = p; /* "pattern" is NULL when there is no pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009015
9016 /* find the index (enum) for the event name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009017 event = event_name2nr(event_name, &p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009018
9019 /* return FALSE if the event name is not recognized */
Bram Moolenaar195d6352005-12-19 22:08:24 +00009020 if (event == NUM_EVENTS)
9021 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009022
9023 /* Find the first autocommand for this event.
9024 * If there isn't any, return FALSE;
9025 * If there is one and no pattern given, return TRUE; */
9026 ap = first_autopat[(int)event];
9027 if (ap == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009028 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009029 if (pattern == NULL)
Bram Moolenaar195d6352005-12-19 22:08:24 +00009030 {
9031 retval = TRUE;
9032 goto theend;
9033 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009034
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009035 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
9036 /* for pattern "<buffer=N>, fnamecmp() will work fine */
9037 if (STRICMP(pattern, "<buffer>") == 0)
9038 buflocal_buf = curbuf;
9039
Bram Moolenaar071d4272004-06-13 20:20:40 +00009040 /* Check if there is an autocommand with the given pattern. */
9041 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009042 /* only use a pattern when it has not been removed and has commands. */
9043 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009044 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaar195d6352005-12-19 22:08:24 +00009045 && (group == AUGROUP_ALL || ap->group == group)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009046 && (buflocal_buf == NULL
9047 ? fnamecmp(ap->pat, pattern) == 0
9048 : ap->buflocal_nr == buflocal_buf->b_fnum))
Bram Moolenaar195d6352005-12-19 22:08:24 +00009049 {
9050 retval = TRUE;
9051 break;
9052 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009053
Bram Moolenaar195d6352005-12-19 22:08:24 +00009054theend:
9055 vim_free(arg_save);
9056 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009057}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00009058
Bram Moolenaar071d4272004-06-13 20:20:40 +00009059#endif /* FEAT_AUTOCMD */
9060
9061#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
9062/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00009063 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
9064 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
9065 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009066 * Used for autocommands and 'wildignore'.
9067 * Returns TRUE if there is a match, FALSE otherwise.
9068 */
9069 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00009070match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009071 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00009072 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009073 char_u *fname; /* full path of file name */
9074 char_u *sfname; /* short file name or NULL */
9075 char_u *tail; /* tail of path */
9076 int allow_dirs; /* allow matching with dir */
9077{
9078 regmatch_T regmatch;
9079 int result = FALSE;
9080#ifdef FEAT_OSFILETYPE
9081 int no_pattern = FALSE; /* TRUE if check is filetype only */
9082 char_u *type_start;
9083 char_u c;
9084 int match = FALSE;
9085#endif
9086
9087#ifdef CASE_INSENSITIVE_FILENAME
9088 regmatch.rm_ic = TRUE; /* Always ignore case */
9089#else
9090 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
9091#endif
9092#ifdef FEAT_OSFILETYPE
9093 if (*pattern == '<')
9094 {
9095 /* There is a filetype condition specified with this pattern.
9096 * Check the filetype matches first. If not, don't bother with the
9097 * pattern (set regprog to NULL).
9098 * Always use magic for the regexp.
9099 */
9100
9101 for (type_start = pattern + 1; (c = *pattern); pattern++)
9102 {
9103 if ((c == ';' || c == '>') && match == FALSE)
9104 {
9105 *pattern = NUL; /* Terminate the string */
9106 match = mch_check_filetype(fname, type_start);
9107 *pattern = c; /* Restore the terminator */
9108 type_start = pattern + 1;
9109 }
9110 if (c == '>')
9111 break;
9112 }
9113
9114 /* (c should never be NUL, but check anyway) */
9115 if (match == FALSE || c == NUL)
9116 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
9117 else if (*pattern == NUL)
9118 {
9119 regmatch.regprog = NULL; /* Vim will try to free regprog later */
9120 no_pattern = TRUE; /* Always matches - don't check pat. */
9121 }
9122 else
9123 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
9124 }
9125 else
9126#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00009127 {
9128 if (prog != NULL)
9129 regmatch.regprog = prog;
9130 else
9131 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
9132 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009133
9134 /*
9135 * Try for a match with the pattern with:
9136 * 1. the full file name, when the pattern has a '/'.
9137 * 2. the short file name, when the pattern has a '/'.
9138 * 3. the tail of the file name, when the pattern has no '/'.
9139 */
9140 if (
9141#ifdef FEAT_OSFILETYPE
9142 /* If the check is for a filetype only and we don't care
9143 * about the path then skip all the regexp stuff.
9144 */
9145 no_pattern ||
9146#endif
9147 (regmatch.regprog != NULL
9148 && ((allow_dirs
9149 && (vim_regexec(&regmatch, fname, (colnr_T)0)
9150 || (sfname != NULL
9151 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
9152 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
9153 result = TRUE;
9154
Bram Moolenaar748bf032005-02-02 23:04:36 +00009155 if (prog == NULL)
9156 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009157 return result;
9158}
9159#endif
9160
9161#if defined(FEAT_WILDIGN) || defined(PROTO)
9162/*
9163 * Return TRUE if a file matches with a pattern in "list".
9164 * "list" is a comma-separated list of patterns, like 'wildignore'.
9165 * "sfname" is the short file name or NULL, "ffname" the long file name.
9166 */
9167 int
9168match_file_list(list, sfname, ffname)
9169 char_u *list;
9170 char_u *sfname;
9171 char_u *ffname;
9172{
9173 char_u buf[100];
9174 char_u *tail;
9175 char_u *regpat;
9176 char allow_dirs;
9177 int match;
9178 char_u *p;
9179
9180 tail = gettail(sfname);
9181
9182 /* try all patterns in 'wildignore' */
9183 p = list;
9184 while (*p)
9185 {
9186 copy_option_part(&p, buf, 100, ",");
9187 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
9188 if (regpat == NULL)
9189 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00009190 match = match_file_pat(regpat, NULL, ffname, sfname,
9191 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009192 vim_free(regpat);
9193 if (match)
9194 return TRUE;
9195 }
9196 return FALSE;
9197}
9198#endif
9199
9200/*
9201 * Convert the given pattern "pat" which has shell style wildcards in it, into
9202 * a regular expression, and return the result in allocated memory. If there
9203 * is a directory path separator to be matched, then TRUE is put in
9204 * allow_dirs, otherwise FALSE is put there -- webb.
9205 * Handle backslashes before special characters, like "\*" and "\ ".
9206 *
9207 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
9208 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
9209 *
9210 * Returns NULL when out of memory.
9211 */
9212/*ARGSUSED*/
9213 char_u *
9214file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
9215 char_u *pat;
9216 char_u *pat_end; /* first char after pattern or NULL */
9217 char *allow_dirs; /* Result passed back out in here */
9218 int no_bslash; /* Don't use a backward slash as pathsep */
9219{
9220 int size;
9221 char_u *endp;
9222 char_u *reg_pat;
9223 char_u *p;
9224 int i;
9225 int nested = 0;
9226 int add_dollar = TRUE;
9227#ifdef FEAT_OSFILETYPE
9228 int check_length = 0;
9229#endif
9230
9231 if (allow_dirs != NULL)
9232 *allow_dirs = FALSE;
9233 if (pat_end == NULL)
9234 pat_end = pat + STRLEN(pat);
9235
9236#ifdef FEAT_OSFILETYPE
9237 /* Find out how much of the string is the filetype check */
9238 if (*pat == '<')
9239 {
9240 /* Count chars until the next '>' */
9241 for (p = pat + 1; p < pat_end && *p != '>'; p++)
9242 ;
9243 if (p < pat_end)
9244 {
9245 /* Pattern is of the form <.*>.* */
9246 check_length = p - pat + 1;
9247 if (p + 1 >= pat_end)
9248 {
9249 /* The 'pattern' is a filetype check ONLY */
9250 reg_pat = (char_u *)alloc(check_length + 1);
9251 if (reg_pat != NULL)
9252 {
9253 mch_memmove(reg_pat, pat, (size_t)check_length);
9254 reg_pat[check_length] = NUL;
9255 }
9256 return reg_pat;
9257 }
9258 }
9259 /* else: there was no closing '>' - assume it was a normal pattern */
9260
9261 }
9262 pat += check_length;
9263 size = 2 + check_length;
9264#else
9265 size = 2; /* '^' at start, '$' at end */
9266#endif
9267
9268 for (p = pat; p < pat_end; p++)
9269 {
9270 switch (*p)
9271 {
9272 case '*':
9273 case '.':
9274 case ',':
9275 case '{':
9276 case '}':
9277 case '~':
9278 size += 2; /* extra backslash */
9279 break;
9280#ifdef BACKSLASH_IN_FILENAME
9281 case '\\':
9282 case '/':
9283 size += 4; /* could become "[\/]" */
9284 break;
9285#endif
9286 default:
9287 size++;
9288# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009289 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009290 {
9291 ++p;
9292 ++size;
9293 }
9294# endif
9295 break;
9296 }
9297 }
9298 reg_pat = alloc(size + 1);
9299 if (reg_pat == NULL)
9300 return NULL;
9301
9302#ifdef FEAT_OSFILETYPE
9303 /* Copy the type check in to the start. */
9304 if (check_length)
9305 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
9306 i = check_length;
9307#else
9308 i = 0;
9309#endif
9310
9311 if (pat[0] == '*')
9312 while (pat[0] == '*' && pat < pat_end - 1)
9313 pat++;
9314 else
9315 reg_pat[i++] = '^';
9316 endp = pat_end - 1;
9317 if (*endp == '*')
9318 {
9319 while (endp - pat > 0 && *endp == '*')
9320 endp--;
9321 add_dollar = FALSE;
9322 }
9323 for (p = pat; *p && nested >= 0 && p <= endp; p++)
9324 {
9325 switch (*p)
9326 {
9327 case '*':
9328 reg_pat[i++] = '.';
9329 reg_pat[i++] = '*';
Bram Moolenaar02743632005-07-25 20:42:36 +00009330 while (p[1] == '*') /* "**" matches like "*" */
9331 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009332 break;
9333 case '.':
9334#ifdef RISCOS
9335 if (allow_dirs != NULL)
9336 *allow_dirs = TRUE;
9337 /* FALLTHROUGH */
9338#endif
9339 case '~':
9340 reg_pat[i++] = '\\';
9341 reg_pat[i++] = *p;
9342 break;
9343 case '?':
9344#ifdef RISCOS
9345 case '#':
9346#endif
9347 reg_pat[i++] = '.';
9348 break;
9349 case '\\':
9350 if (p[1] == NUL)
9351 break;
9352#ifdef BACKSLASH_IN_FILENAME
9353 if (!no_bslash)
9354 {
9355 /* translate:
9356 * "\x" to "\\x" e.g., "dir\file"
9357 * "\*" to "\\.*" e.g., "dir\*.c"
9358 * "\?" to "\\." e.g., "dir\??.c"
9359 * "\+" to "\+" e.g., "fileX\+.c"
9360 */
9361 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
9362 && p[1] != '+')
9363 {
9364 reg_pat[i++] = '[';
9365 reg_pat[i++] = '\\';
9366 reg_pat[i++] = '/';
9367 reg_pat[i++] = ']';
9368 if (allow_dirs != NULL)
9369 *allow_dirs = TRUE;
9370 break;
9371 }
9372 }
9373#endif
9374 if (*++p == '?'
9375#ifdef BACKSLASH_IN_FILENAME
9376 && no_bslash
9377#endif
9378 )
9379 reg_pat[i++] = '?';
9380 else
9381 if (*p == ',')
9382 reg_pat[i++] = ',';
9383 else
9384 {
9385 if (allow_dirs != NULL && vim_ispathsep(*p)
9386#ifdef BACKSLASH_IN_FILENAME
9387 && (!no_bslash || *p != '\\')
9388#endif
9389 )
9390 *allow_dirs = TRUE;
9391 reg_pat[i++] = '\\';
9392 reg_pat[i++] = *p;
9393 }
9394 break;
9395#ifdef BACKSLASH_IN_FILENAME
9396 case '/':
9397 reg_pat[i++] = '[';
9398 reg_pat[i++] = '\\';
9399 reg_pat[i++] = '/';
9400 reg_pat[i++] = ']';
9401 if (allow_dirs != NULL)
9402 *allow_dirs = TRUE;
9403 break;
9404#endif
9405 case '{':
9406 reg_pat[i++] = '\\';
9407 reg_pat[i++] = '(';
9408 nested++;
9409 break;
9410 case '}':
9411 reg_pat[i++] = '\\';
9412 reg_pat[i++] = ')';
9413 --nested;
9414 break;
9415 case ',':
9416 if (nested)
9417 {
9418 reg_pat[i++] = '\\';
9419 reg_pat[i++] = '|';
9420 }
9421 else
9422 reg_pat[i++] = ',';
9423 break;
9424 default:
9425# ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009426 if (enc_dbcs != 0 && (*mb_ptr2len)(p) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009427 reg_pat[i++] = *p++;
9428 else
9429# endif
9430 if (allow_dirs != NULL && vim_ispathsep(*p))
9431 *allow_dirs = TRUE;
9432 reg_pat[i++] = *p;
9433 break;
9434 }
9435 }
9436 if (add_dollar)
9437 reg_pat[i++] = '$';
9438 reg_pat[i] = NUL;
9439 if (nested != 0)
9440 {
9441 if (nested < 0)
9442 EMSG(_("E219: Missing {."));
9443 else
9444 EMSG(_("E220: Missing }."));
9445 vim_free(reg_pat);
9446 reg_pat = NULL;
9447 }
9448 return reg_pat;
9449}