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