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