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