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