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