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